Java TCP Socket编程

1.TCP Socket在Java上的实现

Java 为 TCP 协议提供了两个类:Socket 类和 ServerSocket 类。一个 Socket 实例代表了TCP 连接的一端。一个 TCP 连接(TCP connection)是一条抽象的双向信道,两端分别由 IP地址和端口号确定。在开始通信之前,要建立一个 TCP 连接,这需要先由客户端 TCP 向服务器端 TCP 发送连接请求。ServerSocket 实例则监听 TCP 连接请求,并为每个请求创建新的 Socket 实例。也就是说,服务器端要同时处理 ServerSocket 实例和 Socket 实例,而客户端只需要使用 Socket 实例。每个Socket实例会关联一个InputStream和OutputStream对象,我们通过将字节写入套接字的OutputStream来发送数据,并通过从InputStream来接收数据。

2.TCP连接的建立步骤

  客户端向服务器端发送连接请求后,就被动地等待服务器的响应。典型的TCP客户端要经过下面三步操作: 

   1、创建一个Socket实例:构造函数向指定的远程主机和端口建立一个TCP连接;

   2.通过套接字的I/O流与服务端通信;

   3、使用Socket类的close方法关闭连接。

 

  服务端的工作是建立一个通信终端,并被动地等待客户端的连接。典型的TCP服务端执行如下两步操作:

     1、创建一个ServerSocket实例并指定本地端口,用来监听客户端在该端口发送的TCP连接请求;

     2、重复执行:

           1)调用ServerSocket的accept()方法以获取客户端连接,并通过其返回值创建一个Socket实例;

           2)为返回的Socket实例开启新的线程,并使用返回的Socket实例的I/O流与客户端通信;

           3)通信完成后,使用Socket类的close()方法关闭该客户端的套接字连接

        绘图1

3.TCP Demo

Demo1.基本的流发送示例:

服务端开启一个TCP服务器,参数为端口号

客户端启动一个TCP服务,参数为服务端的地址,发送的字符,端口号

 1 import java.net.Socket;
 2 import java.net.SocketException;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.io.OutputStream;
 6 
 7 public class TCPClient {
 8 
 9     public static void main(String[] args) throws IOException {
10 
11         if ((args.length < 2) || (args.length > 3))
12 
13             throw new IllegalArgumentException(
14                     "Parameter(s):<Server> <Word> [<Port>]");
15 
16         String server = args[0]; // Server name or IP address
17         /* Convert argument String to bytes using the default character encoding */
18         byte[] senddata = args[1].getBytes();
19         int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;
20         /* Create socket that is connected to server onspecified port*/
21         Socket socket = new Socket(server, servPort);
22         System.out.println("Connected to server...sending echo string");
23 
24         InputStream in = socket.getInputStream();
25         OutputStream out = socket.getOutputStream();
26         out.write(senddata); // Send the encoded string to the server
27 
28         int totalBytesRcvd = 0; // Total bytes received so far
29         byte[] recvdata = new byte[in.available()];
30         int bytesRcvd; // Bytes received in last read
31         while (totalBytesRcvd < recvdata.length) {
32             if ((bytesRcvd = in.read(recvdata, totalBytesRcvd, recvdata.length
33                     - totalBytesRcvd)) == -1)
34                 throw new SocketException("Connection closed prematurely");
35             totalBytesRcvd += bytesRcvd;
36         } // data array is full
37 
38         System.out.println("Received: " + new String(recvdata));
39 
40         socket.close(); // Close the socket and its streams
41     }
42 }
TCPClient
 1 import java.net.*; // for Socket, ServerSocket, andInetAddress
 2 import java.io.*; // for IOException and Input/OutputStream
 3 
 4 public class TCPServer {
 5 
 6     private static final int BUFSIZE = 32; // Size of receivebuffer
 7 
 8     public static void main(String[] args) throws IOException {
 9 
10         if (args.length != 1) // Test for correct # of args
11             throw new IllegalArgumentException("Parameter(s): <Port>");
12 
13         int servPort = Integer.parseInt(args[0]);
14 
15         /* Create a server socket to accept client connection requests */
16         ServerSocket servSock = new ServerSocket(servPort);
17 
18         int recvMsgSize; // Size of received message
19         byte[] receiveBuf = new byte[BUFSIZE]; // Receive buffer
20 
21         while (true) { // Run forever, accepting and servicing connections
22 
23             Socket clntSock = servSock.accept(); // Get client connection
24 
25             SocketAddress clientAddress = clntSock.getRemoteSocketAddress();
26 
27             System.out.println("Handling client at " + clientAddress);
28 
29             InputStream in = clntSock.getInputStream();
30             OutputStream out = clntSock.getOutputStream();
31 
32             /* Receive until client closes connection, indicated by -1 return*/
33 
34             while ((recvMsgSize = in.read(receiveBuf)) != -1) {
35 
36                 out.write(receiveBuf, 0, recvMsgSize);
37             }
38             clntSock.close(); // Close the socket. We are done with this client!
39         }
40         /* NOT REACHED */
41 
42     }
43 }
TCPServer

Demo2.

客户端从控制台输入字符串,发送到服务端

服务端受到客户端的字符串后,加上部分信息(echo字符串)返回到客户端

 1 package zyb.org.client;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintStream;
 7 import java.net.Socket;
 8 import java.net.SocketTimeoutException;
 9 
10 public class Client {
11     public static void main(String[] args) throws IOException {
12         //客户端请求与本机在20006端口建立TCP连接 
13         Socket client = new Socket("127.0.0.1", 20006);
14         client.setSoTimeout(10000);
15         //获取键盘输入 
16         BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
17         //获取Socket的输出流,用来发送数据到服务端  
18         PrintStream out = new PrintStream(client.getOutputStream());
19         //获取Socket的输入流,用来接收从服务端发送过来的数据  
20         BufferedReader buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
21         boolean flag = true;
22         while(flag){
23             System.out.print("输入信息:");
24             String str = input.readLine();
25             //发送数据到服务端  
26             out.println(str);
27             if("bye".equals(str)){
28                 flag = false;
29             }else{
30                 try{
31                     //从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常
32                     String echo = buf.readLine();
33                     System.out.println(echo);
34                 }catch(SocketTimeoutException e){
35                     System.out.println("Time out, No response");
36                 }
37             }
38         }
39         input.close();
40         if(client != null){
41             //如果构造函数建立起了连接,则关闭套接字,如果没有建立起连接,自然不用关闭
42             client.close();    //只关闭socket,其关联的输入输出流也会被关闭
43         }
44     }
45 }
客户端代码Client
 1 package zyb.org.server;
 2 
 3 import java.net.ServerSocket;
 4 import java.net.Socket;
 5 
 6 public class Server {
 7     public static void main(String[] args) throws Exception{
 8         //服务端在20006端口监听客户端请求的TCP连接
 9         ServerSocket server = new ServerSocket(20006);
10         Socket client = null;
11         boolean f = true;
12         while(f){
13             //等待客户端的连接,如果没有获取连接
14             client = server.accept();
15             System.out.println("与客户端连接成功!");
16             //为每个客户端连接开启一个线程
17             new Thread(new ServerThread(client)).start();
18         }
19         server.close();
20     }
21 }
服务端代码Server
 1 package zyb.org.server;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.InputStreamReader;
 5 import java.io.PrintStream;
 6 import java.net.Socket;
 7 
 8 /**
 9  * 该类为多线程类,用于服务端
10  */
11 public class ServerThread implements Runnable {
12 
13     private Socket client = null;
14     public ServerThread(Socket client){
15         this.client = client;
16     }
17     
18     @Override
19     public void run() {
20         try{
21             //获取Socket的输出流,用来向客户端发送数据
22             PrintStream out = new PrintStream(client.getOutputStream());
23             //获取Socket的输入流,用来接收从客户端发送过来的数据
24             BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
25             boolean flag =true;
26             while(flag){
27                 //接收从客户端发送过来的数据
28                 String str =  buf.readLine();
29                 if(str == null || "".equals(str)){
30                     flag = false;
31                 }else{
32                     if("bye".equals(str)){
33                         flag = false;
34                     }else{
35                         //将接收到的字符串前面加上echo,发送到对应的客户端
36                         out.println("echo:" + str);
37                     }
38                 }
39             }
40             out.close();
41             client.close();
42         }catch(Exception e){
43             e.printStackTrace();
44         }
45     }
46 
47 }
服务端代码 线程类 ServerThread

 

参考文章:

【Java TCP/IP Socket】TCP Socket(含代码)  http://blog.csdn.net/ns_code/article/details/14105457

《Java TCP/IP Socket 编程》 

 

posted @ 2015-01-26 16:32  xerrard  阅读(937)  评论(0编辑  收藏  举报