一:TCP协议基础

  TCP/IP通信协议是一种可靠的网络协议,他在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。

  Java对基于TCP协议的网络通信提供了良好的封装,它使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。

二:使用ServerSocket创建TCP服务器端

  在两个通信实体建立虚拟链路之前,必须有一个通信实体(服务器端,Server)先做出“主动姿态”去接收来自其他通信实体(客户端,Client)的连接请求。

  Java中能接受其他通信实体连接请求的类是ServerSocketServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,他将一直处于等待状态。

  ServerSocket包含一个监听来自客户端连接请求的方法:Socket accept() :如果接受到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket;否则该方法将一直处于等待状态,线程也被阻塞。

为创建ServerSocket对象,ServerSocket类提供了如下几个构造器:

  ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该有一个有效的端口整数值:0~65535。

  ServerSocket(int port,int backlog):backlog:用来改变连接队列的长度。      

  ServerSocket(int port,int backlog,InetAddress localAddr): 在机器存在多个IP地址的情况下,允许通过localAddr这个参数来指定将ServerSocket绑定到指定的IP地址。

  当ServerSocket使用完毕,应使用ServerSocket的close()方法来关闭该ServerSocket。通常情况下,服务器不应该只接受一个客户端请求,而应该不断的接受来自客户端的所有请求,所以Java程序通常会通过循环,不断地调用ServerSocket的accept()方法。

【代码示例】

//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
//采用循环不断接受来自客户端的请求
while (true)
{ //每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
//下面就可以使用Socket进行通信了 }

三、使用Socket进行通信

  客户端可使用Socket的构造器来连接到指定服务器,Socket通常可使用如下两个构造器:

Socket(InetAddress/String remoteAddress,int port)

创建连接到指定远程主机、远程端口的Socket。该构造器没有指定本地地址、本地端口,默认使用本机默认IP地址,系统动态分配端口。

Socket(InetAddress/String remoteAddress,int port,InetAddress localAddr,int localPort)

创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口,适用于本地主机有多个IP地址的情形。

  上面两个构造器中指定远程主机时既可使用InetAddress来指定,也可直接使用String对象来指定,通常使用String对象来指定远程主机IP地址。当本地主机只有一个IP地址时,使用第一个方法更为简单。

【示例代码】

//创建连接到本机、30000端口的Socket
Socket s = new Socket("127.0.0.1", 30000);
//下面就可以使用Socket进行通信了
  当程序执行上面代码时,该代码将会连接到指定服务器,让服务器端的ServerSocket的accept()方法向下执行,于是服务器端和客户端就产生一对相互连接的Socket。
  当客户端、服务器端产生了对应的Socket之后,程序无须再区分服务器、客户端,而是通过各自的Socket进行通信,Socket提供如下两个方法来获取输入流和输出流:
getInputStream()
返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。
getOutputStream()
返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据。
  当程序执行上面代码时,该代码将会连接到指定服务器,让服务器端的ServerSocket的accept()方法向下执行,于是服务器端和客户端就产生一对相互连接的Socket。

四、Java最简TCP通信程序实例:

1、服务器端程序代码Server.java

  此程序仅仅建立ServerSocket监听,并使用Socket获取输出流输出。
import java.net.*;
import java.io.*;public class Server
{
public static void main(String[] args)
throws IOException
{
//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
//采用循环不断接受来自客户端的请求
while (true)
{
//每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
//将Socket对应的输出流包装成PrintStream
PrintStream ps = new PrintStream(s.getOutputStream());
//进行普通IO操作
ps.println("您好,您收到了服务器端的数据!");
//关闭输出流,关闭Socket
ps.close();
s.close();
}
}
}

 

 

2、客户端程序Client.java

  此程序仅仅使用Socket建立与指定IP、指定端口的连接,并使用Socket获取输入流读取数据。
import java.net.*;
import java.io.*;public class Client
{
public static void main(String[] args)
throws IOException
{
Socket socket = new Socket("127.0.0.1" , 30000);
//将Socket对应的输入流包装成BufferedReader
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
//进行普通IO操作
String line = br.readLine();
System.out.println("来自服务器的数据:" + line);
//关闭输入流、socket
br.close();
socket.close();
}
}

 

 

 编译以上两个文件后,先运行Server类,在运行Client类,将看到程序的输出数据,表明客户端与服务器端通信成功。

 

 

参考文献:《疯狂Java讲义》