TCP一般用于C/S(客户端/服务器端)模式的应用程序,它们都会存在客户端和服务器端两个部分。
一、服务器端
对于服务器端,使用Java在java.net包下的API,它们的基本编程步骤如下:
(1)创建一个服务器端的Socket,指定一个端口号。Java提供了java.net.ServerSocket类来实现这一步,代码如下:
ServerSocket ss = new ServerSocket(port);
(2)开始监听来自客户端的请求要求。调用ServerSocket的accept()方法即可,代码如下:
ss.accept();
(3)获得输入/输出流。网络也属于I/O的一种,Java也是按照流对待它们,开发者一旦获取这些流对象后,就可以当成普通的文件输入、输出一样来使用。它们都来自于连接成功后的Socket对象,代码如下:
Socket socket = ss.accept();//accept获取socket对象
OutputStream os = socket.getOutputStream();//获得输出流
InputStream is = socket.getInputStream();//获得输入流
(4)调用输入/输出流的read()或write()方法,进行数据的传输。如果是字符数据流则还可以用BufferedReader或PrintWriter进行数据传输,代码如下:
OutputStream os = s.getOutputStream();//获得输出流
PrintWriter pw = new PrintWriter(os);//创建PrintWriter对象
pw.print("...");
pw.flush();//把缓存中的数据发送到对端,否则可能造成数据不能及时送达的后果
//或者
InputStream is = ss.getInputStream();//获得输入流
InputStreamRreader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
(5)释放资源。关闭输入/输出流、Socket和ServerSocket对象,代码如下:
pw.close();//关闭输出流
socket.colse();//关闭socket
ss.close();//关闭serverSocket
二、客户端
客户端的编程步骤基本差不多,只是少了创建ServerSocket对象,它直接去连接服务器端即可,步骤如下:
(1)创建Socket对象,建立与服务器端的连接,代码如下:
Socket socket = new Socket(IP, port);
(2)获取输入/输出流;
(3)调用输入/输出流的read()或wirte()方法,进行数据传输;
(4)释放资源,关闭输入/输出流、socket对象;
三、TCP编程示例
1、把服务器端时间发送到客户端
(服务器端)
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class TCPServer01 {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);//用端口号创建ServerSocket对象
Socket socket = ss.accept();//监听来自客户端的请求
OutputStream os = socket.getOutputStream();//获得输出流
PrintWriter pw = new PrintWriter(os);//创建PrintWriter对象
pw.print("now time = " + new Date());//向输出流中写入当前时间
pw.flush();//清空缓存
//关闭输出流和Socket
pw.close();
socket.close();
ss.close();
}
}
(客户端)
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class TCPClient01 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 8888);//用IP地址和端口创建Socket对象
InputStream is = socket.getInputStream();//获得输入流
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String str = br.readLine();//读取数据
System.out.println(str);//打印从服务器端来的数据
}
}
(服务器端)
public class TCPServer02 {
private final static int BUFSIZE = 32;//Size of receive buffer
public static void main(String[] args) throws IOException {
if(args.length != 1)
throw new IllegalArgumentException("Parameter(s):<Port>");
int servPort = Integer.parseInt(args[0]);
// Create a server socket to accept client connection requests
ServerSocket servSock = new ServerSocket(servPort);
int recvMsgSize;// Size of received message
byte[] receiveBuf = new byte[BUFSIZE];//Receive buffer
while(true){//Run forever, accepting and servicing connections
Socket clientSock = servSock.accept();//Get client connection
SocketAddress clientAddress = clientSock.getRemoteSocketAddress();
System.out.println("Handling client at " + clientAddress);
InputStream in = clientSock.getInputStream();
OutputStream out = clientSock.getOutputStream();
// Receive until client closes connection, indicated by -1 return
while((recvMsgSize = in.read(receiveBuf)) != -1)
out.write(receiveBuf, 0, recvMsgSize);
clientSock.close();//Close the socket.
}
}
}
(客户端)
public class TCPClient02 {
public static void main(String[] args) throws IOException {
if((args.length < 2) || (args.length > 3))
throw new IllegalArgumentException("Parameter(s):<Server><Word>[<Port>]");
String server = args[0];//Server name or IP address
byte[] data = args[1].getBytes();// Convert argument String to bytes using the default character encoding
int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;//Set the server port
// Create socket that is connected to server on specified port
Socket socket = new Socket(server, servPort);
System.out.println("Connected to server... sending echo string");
//Socket的输入输出流
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
//write()方法将指定的字节数组通过之前建立好的连接,传送到指定的服务器
out.write(data);//Send the encoded string to the server
//Receive the same string back from the server
int totalBytesRcvd = 0;//Total bytes received so far
int bytesRcvd;//Bytes received int last read
while(totalBytesRcvd < data.length){
//知道要从回馈服务器接收的字节数,就可以重复执行接收过程,直到接收了发送字节数相等的信息
//所以这里read()需要3个参数:1)接收数据的数组;2)接收的第一个字节应该放入数组的位置;3)放入数组的最大字节数
if((bytesRcvd = in.read(data, totalBytesRcvd,data.length - totalBytesRcvd)) == -1)
throw new SocketException("Connection closed prematurelly");
totalBytesRcvd += bytesRcvd;
}//data array is full
System.out.println("Received: " + new String(data));
socket.close();//Close the socket and its stream
}
}