在Java中,有三种套接字类:java.net.Socket、java.net.ServerSocket和DatagramSocket。其中Socket和ServerSocket类建立在TCP协议基础上,DatagramSocket类建立在UDP协议基础上。
传输层向应用层提供了套接字Socket 接口,Socket 封装了下层的数据传输细节,应用层的程序通过Socket来建立与远程主机的连接以及进行数据传输。
下面例子,模拟多个用户同时连接服务器,服务器收到一个客户连接申请时,就启动一个线程进行处理。
服务器类ServerSocketServer.java
package socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketServer {
public static void main(String[] args)throws Exception {
new ServerSocketServer().service();
}
private int port=8888;//监听端口
private ServerSocket serverSocket;
public ServerSocketServer()throws Exception{
serverSocket=new ServerSocket(port);
System.out.println("服务器启动了.........");
}
public void service(){
while(true){
Socket socket=null;
//进入阻塞,等待客户端的连接
//如果客户端申请连接,则返回一个Socket对象,该对象和客户端的Socket对象构成一条通信渠道
try {
socket=serverSocket.accept();
new SocketThread(socket).start();//有一个客户申请连接,就启动一个线程进行处理(可以考虑用线程池管理)
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class SocketThread extends Thread{
private Socket socket=null;
public SocketThread(Socket socket){
this.socket=socket;
}
public void run(){
try {
String user=socket.getInetAddress()+":"+socket.getPort();
System.out.println("新客户到来:"+user);
//读取客户端发送类的内容
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
//向客户端发送信息
PrintWriter writer=new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
while(true){
String content=reader.readLine();
if(content==null) break;
System.out.println("客户端"+user+"对服务器说:"+content);
//服务器向客户端发送信息
//所以必须使用println()输出
//如果用print输出,则content必须加\r\n(content+"\r\n"),否则客户端的readLine()会无法读取,一直阻塞
// writer.print(content+"\r\n");//原样发回
writer.println(content);
writer.flush();
if("bye".equalsIgnoreCase(content))
break;//结束通信
}
reader.close();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(socket!=null)
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}//通信结束
}
}
}
}
客户端类ClientSocket.java
package socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class ClientSocket {
public static void main(String[] args)throws Exception {
new ClientSocket().talk();
}
private String host="localhost";
private int port=8888;
private Socket socket;
public ClientSocket()throws Exception{
socket=new Socket(host,port);
}
private void talk(){
try {
//从键盘接收输入(输入是中文的话,就乱码了,估计和OS的字符集有关)
BufferedReader readerLocal=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
//从服务器接收信息
BufferedReader readerServer=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
//向服务器发送
PrintWriter writer=new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
while(true){
System.out.print("客户端往服务器发送信息:");
String msg=readerLocal.readLine();//接收来自键盘的内容
if(msg==null || "".equalsIgnoreCase(msg)) break;
//服务器使用BufferedReader中的readLine()读取的
//所以必须使用println()输出
//如果用print输出,则msg必须加\r\n(msg+"\r\n"),否则服务器的readLine()会无法读取,一直阻塞
//writer.print(msg+"\r\n");
writer.println("bye".equalsIgnoreCase(msg)?msg:(msg+"好"));//加个"好"字,是为了测试socket传输中文是否正常,结论正常
writer.flush();
System.out.println("客户端接收到来自服务器的信息:"+readerServer.readLine());
if("bye".equalsIgnoreCase(msg))
break;
}
readerLocal.close();
readerServer.close();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.启动服务器
2.启动客户端,发送内容a,bye
3.启动客户端,发送内容b,bye
2,3是同时存在的
本文介绍了一个基于 Java 的 Socket 服务器实现,该服务器能够处理多个客户端的同时连接请求,并为每个客户端分配独立的线程进行数据交换。文章还提供了一个简单的客户端示例,用于与服务器进行交互。
902

被折叠的 条评论
为什么被折叠?



