该例子可以实现多个客户端的聊天室功能,即任何一个客户端发送消息给服务器,服务器会转发给所有与它连接的客户端。因为服务器要维护与多个客户端的连接,这里用线程实现,每个客户端和服务器端连接后,服务器端都会开启一个线程,用于接收当前这个客户端的消息,并转发给所有的客户端。
该例子由3个Java类实现,客户端:tcp. EchoMultiClient,服务器端:tcp. EchoMultiServer,tcp.EchoServerThread(服务器端使用的线程类)。
客户端类,该客户端发送消息和接收消息分别在一个线程中进行:
代码语言:javascript复制package test;
import java.util.List;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MultiServer {
ServerSocket serverSocket;
List<Socket> clients=new ArrayList<Socket>();
public MultiServer() {
try {
serverSocket=new ServerSocket(7);
while(true) {
Socket clientSocket=serverSocket.accept();
clients.add(clientSocket);
new EchoServerThread(clientSocket,clients).start();
}
}catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new MultiServer();
}
}
服务器端代码,该代码中每监听到客户端的一个连接,就调用线程类创建并启动一个线程对象。
服务器端代码:
代码语言:javascript复制package test;
import java.util.List;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MultiServer {
ServerSocket serverSocket;
List<Socket> clients=new ArrayList<Socket>();
public MultiServer() {
try {
serverSocket=new ServerSocket(7);
while(true) {
Socket clientSocket=serverSocket.accept();
clients.add(clientSocket);
new EchoServerThread(clientSocket,clients).start();
}
}catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new MultiServer();
}
}
服务器端使用的线程类代码:
代码语言:javascript复制package test;
//服务器端使用的线程类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
public class EchoServerThread extends Thread{
Socket myClient;
List<Socket> clients;
String clientHostName;
int clientPort;
public EchoServerThread(Socket myClient,List<Socket> clients) {
super();
this.myClient=myClient;
this.clients=clients;
}
public void run() {
InetSocketAddress clientAddress=(InetSocketAddress)myClient.getRemoteSocketAddress();
clientHostName=clientAddress.getHostName();
clientPort=clientAddress.getPort();
System.out.println("第" clients.size() "个客户端" clientHostName ":" clientPort "已连接");
try {
String inStr;
BufferedReader in=new BufferedReader(new InputStreamReader(myClient.getInputStream()));
while((inStr=in.readLine())!=null) {
System.out.println(inStr ".来自" clientHostName ":" clientPort "");
for(Socket client:clients) {
if(client!=null) {
PrintWriter out=new PrintWriter(client.getOutputStream(),true);
out.println(inStr ".来自" clientHostName ":" clientPort "");
}
}
}
}catch(IOException e) {
System.err.println(clientHostName ":" clientPort "退出了.");
}
}
}
该程序运行时,先启动服务器端代码,再多次启动客户端。
例如以下运行效果,启动了服务器端后,启动了3次客户端,3个客户端分别发送消息,效果如下:
效果图: