在Java Socket(下)中写了服务器端和客户端进行通信的例子,但是在实际应用当中,不是这样的一对一通信,通常都是一台服务器,对应着很多很多客户端进行通信,可以通过多线程来实现多客户端与服务器端进行通信。
(注:只是根据所学知识点写一个小例子,线程安全暂未考虑进去)
首先是Server端的代码段:
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
int count = 0; //用来保存有多少个客户端
Socket socket = null;
ServerSocket server = null;
try {
server = new ServerSocket(8888);
System.out.println("***服务器即将启动,等待客户端的连接***");
//循环监听等待客户端的请求
while (true) {
try {
//监听客户端的请求,接收成功得到一个socket对象
socket = server.accept();
//创建一个新线程
ServerThread thread = new ServerThread(socket);
//启动线程
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
count++;
System.out.println("客户端进程个数: " + count);
InetAddress inetAddress = socket.getInetAddress();
System.out.println("客户端的IP地址是: " + inetAddress.getHostAddress());
}
} catch (IOException e1) {
e1.printStackTrace();
}finally { //关闭资源
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ServerThread类负责处理Socket通信的业务逻辑,对应处理每一个客户端线程:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class ServerThread extends Thread{
//和本线程相关的socket
private Socket socket;
private InputStream inputStream = null;
private InputStreamReader inputStreamReader = null;
private BufferedReader bufferedReader = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
inputStream = socket.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
String info = null;
while ((info = bufferedReader.readLine()) != null) {
System.out.println("我是服务器,客户端说: " + info);
}
socket.shutdownInput();
} catch (IOException e) {
e.printStackTrace();
}finally { //为避免发生内存泄漏,应该将关闭资源的语句放在finally块中
try {
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端代码段:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
try {
//1、创建客户端Socket,指定服务器地址和端口
Socket socket = new Socket("localhost", 8888); //也可以写成:new Socket("127.0.0.1", 8888);
//2、获取输出流,向服务器发送信息
OutputStream os = socket.getOutputStream(); //字节输出流
PrintWriter pw = new PrintWriter(os); //将输出流包装为打印流
pw.write("用户名: teacher; 密码: 789");
pw.flush();
socket.shutdownOutput(); //关闭输出流
//3、关闭资源
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
不断地修改客户端要发送给服务器端的message,不断地运行客户端程序,可以模拟多个客户端与服务器进行通信,在此期间,客户端运行完一次就结束了,但是服务器端在与一个客户端结束通信之后,并未停止运行,仍然在监听客户端的通信请求,当再次运行客户端程序时,对于服务器端而言,线程数+1。
修改了三次客户端的数据,运行三次客户端程序的运行结果:
(右上角:服务器端程序仍然在运行)