Java 为TCP 协议提供了两个类: Socket 类和ServerSocket 类.一个Socket 实例表示了TCP连接的一端。ServerSocket 实例监听TCP连接请求,并为每个请求创建新的Socket 实例。
也就是说服务器端要同时处理ServerSocket 实例和Socket实例, 客户端只需要使用 Socket 实例.
先看一个实例:
第一部分 创建TCP客户端,步骤如下:
1 创建一个Socket实例,构造函数向指定的远程主机和端口建立一个TCP连接
2 通过Socket套接字的输入输出流(I/O Stream) 进行通信
3 使用Socket类的close()关闭连接
代码:
/**
* 通过TCP协议与回馈服务器(echo server)进行通信的客户端
* 运行时参数 www.mkp.com "Echo this!" 80
* 或 173.245.60.120 "Echo this!" 80
*/
public class TCPEchoClient {
public static void main(String[] args) throws IOException
{
if(args.length < 2 || args.length > 3)
throw new IllegalArgumentException("参数长度"+args.length+" Parameter(s):<Server> <Word> <Port>");
String server = args[0];
byte[] data = args[1].getBytes();
int serverPort = (args.length == 3)?Integer.parseInt(args[2]) : 7;
//创建连接到服务器Socket套接字连接
System.out.println("server: "+server + " serverPort: "+serverPort);
Socket socket = new Socket(server,serverPort);
System.out.println("连接到服务器... 发送响应字符");
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
// 发送编码字符到服务端,这里写就是发送
out.write(data);
System.out.println("第二个参数字符"+args[1].toString());
//以下从服务端接受相同的字符
int totalBytesReceived = 0; // 读取起点
int bytesRcvd; // 最后一次读取的字符数
while(totalBytesReceived < data.length)
{
/**
* 说明: 为什么不用不带参数的 read()方法?TCP协议并不能确定在read()和write()中所发送信息的界限
* 也就是说,虽然只用了write()方法来发送响应字符串,响应服务器也可能从多个块(chunk)中接受该信息
* 即使响应字符串在服务器上存于一个块中,在返回的时候,也可能被TCP协议分割成多个部分
*/
bytesRcvd = in.read(data,totalBytesReceived,data.length - totalBytesReceived);
if(bytesRcvd == -1)// -1 表示已读到最后
throw new SocketException("Connectin closed prematurely"); //关闭连接过早,这里读就是接受
totalBytesReceived += bytesRcvd;
}
System.out.println("Received: " + new String(data));
socket.close();
}
}
第二部分 创建TCP服务端,步骤如下:
1 创建一个ServerSocket 实例并指定本地端口。
2 重复执行:
a 调用ServerSocket的accept() 方法以获取下一个客户端连接
b 使用所返回的Socket 实例的InputStream 和 OutputStream 与客户端进行通信
c 通信完成后,使用Socket 类的close() 关闭该客户端套接字连接
代码如下:
/**
* TCP 服务器端
* 运行参数 80
*/
public class TCPEchoServer {
private static final int BUFSIZE = 32;
public static void main(String[] args)throws IOException {
if(args.length !=1)throw new IllegalArgumentException("Parameter(s): <Port>");
int serverPort = Integer.parseInt(args[0]);
//创建一个socket 服务连接,用于接受客户端连接请求
ServerSocket serverSocket = new ServerSocket(serverPort);
int recMsgSize;
byte[] receiveBuf = new byte[BUFSIZE]; //接收缓冲字符
while(true)
{
Socket clientSocket = serverSocket.accept();
SocketAddress clientAddress = clientSocket.getRemoteSocketAddress();
System.out.println("处理客户端请求在 " + clientAddress);
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
//接受请求直到客户端关闭连接,显式由 -1 返回
while((recMsgSize = in.read(receiveBuf)) != -1)
{
out.write(receiveBuf,0,recMsgSize);
}
clientSocket.close();
}
}
}
效果如下: