TCP 的 Java 支持
协议相当于相互通信的程序间达成的一种约定,它规定了分组报文的结构、交换方式、包含的意义以及怎样对报文所包含的信息进行解析,TCP/IP 协议族有 IP 协议、TCP 协议和 UDP 协议。现在 TCP/IP 协议族中的主要 socket 类型为流套接字(使用 TCP 协议)和数据报套接字(使用 UDP 协议)。
Socket套接字 是面向连接的通信,基于TCP/IP协议提供了稳定的支持(Ps: TCP/IP 传输效率低于 UDP),TCP/IP 提供了Socket和Serversocket两个类, 使用 Serversocket 实例来监听端口是否 有客户端请求,并通过 accept()方法 来返回一个Socket 实例,客户端的socket和服务端的socket 就这样建立了连接,每个socket 有自己的io流 ,那么服务端的输入流对应客户端的输出流,客户端的输出流对应服务端的输入流,在这里输入流 我们采用(BufferedReader)包装流,输入采用(PrintStream)包装流,通过包装流 包装 输入输初流,可以方便程序数据的使用。
典型的 TCP 服务端执行如下两步操作:
创建一个 ServerSocket 实例并指定本地端口,用来监听客户端在该端口发送的 TCP 连接请求;
重复执行:
调用 ServerSocket 的 accept()方法以获取客户端连接,并通过其返回值创建一个 Socket 实例;
为返回的 Socket 实例开启新的线程,并使用返回的 Socket 实例的 I/O 流与客户端通信; 通信完成后,使用 Socket 类的 close()方法关闭该客户端的
套接字连接。
好了话不多说,下面贴程序。
***服务端代码***
1 package socket多客户端; 2 3 4 import java.io.IOException; 5 import java.net.*; 6 import java.util.ArrayList; 7 public class Server { 8 9 private static ArrayList<Thread_Client> list = new ArrayList<>();10 11 private static final int PORT = 6789;12 private static ServerSocket serverSocket;13 private static Socket socket;14 15 static void send(String string){16 17 // 使用 for 循环 , 遍历Arraylist 广播某客户端传来的消息18 for(Thread_Client thread_Client : list){19 // 调用 子线程的 send 方法20 thread_Client.send(string);21 }22 23 }24 25 26 public static void main(String[] args) {27 28 29 30 System.out.println("服务端开始运行...");31 32 try {33 34 serverSocket = new ServerSocket(PORT);35 36 while(true){37 socket = serverSocket.accept();38 Thread_Client thread_Client = new Thread_Client(socket);39 thread_Client.start();40 System.out.println("已连接!");41 list.add(thread_Client);42 43 }44 45 46 } catch (Exception e) {47 // TODO: handle exception48 System.out.println("服务端异常1");49 }finally {50 51 try {52 socket.close();53 serverSocket.close();54 55 } catch (IOException e2) {56 // TODO: handle exception57 System.out.println("服务端异常2");58 }59 60 }61 62 }63 64 }
*** 然后是 处理连接后socket 的子线程***
1 package socket多客户端; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.PrintStream; 7 import java.lang.*; 8 import java.net.Socket; 9 10 public class Thread_Client extends Thread{11 12 private BufferedReader bufferedReader = null;13 private PrintStream printStream = null;14 15 Socket socket;16 17 public Thread_Client(Socket socket) {18 //19 this.socket = socket;20 }21 22 @Override23 public void run() {24 // TODO Auto-generated method stub25 super.run();26 27 try {28 Get_Set(socket);29 30 } catch (Exception e) {31 // TODO: handle exception32 System.out.println("异常1");33 }34 35 }36 37 public void send(String string){38 if(string != null){39 printStream.println(string);40 printStream.flush();41 }42 }43 44 public void Get_Set(Socket socket){45 46 try {47 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));48 printStream = new PrintStream(socket.getOutputStream());49 50 Boolean flag = true;51 while(flag){52 String string = bufferedReader.readLine();53 if("".equals(string) || string == null){54 flag = false;55 }else{56 if("end".equals(string)){57 flag = false;58 }else{59 System.out.println("read : " + string);60 //调用 主线程 广播61 Server.send(string);62 }63 }64 }65 66 } catch (IOException e) {67 // TODO: handle exception68 System.out.println("异常2");69 }70 }71 72 }
*** 最后是 客户端代码 ***
1 package socket多客户端; 2 3 import java.io.*; 4 import java.net.*; 5 import java.util.Scanner; 6 7 public class Client { 8 9 10 private static Socket socket; 11 private static BufferedReader bufferedReader; 12 private static PrintStream printStream; 13 14 // 将 读服务端数据封装在 Client—read 方法里 15 public static void Client_read(Socket socket){ 16 // 匿名内部类 开 一个子线程 17 new Thread(new Runnable() { 18 private BufferedReader bufferedReader_ec; 19 20 @Override 21 public void run() { 22 // TODO Auto-generated method stub 23 24 try { 25 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 26 String str = bufferedReader.readLine(); 27 if("".equals(str) || str == null || "end".equals(str)){ 28 29 }else{ 30 System.out.println(str); 31 } 32 33 } catch (Exception e) { 34 // TODO: handle exception 35 } 36 } 37 }).start(); 38 } 39 40 // Get_Set 方法 处理 客户端与服务端 数据的读写 41 static void Get_Set(Socket socket){ 42 43 try { 44 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 45 printStream = new PrintStream(socket.getOutputStream()); 46 Scanner keyboard = new Scanner(System.in); 47 48 Boolean flag = true; 49 while(flag){ 50 51 // 在这里调用 之前封装的 Client_read 方法 52 Client_read(socket); 53 54 // 从 键盘 输入数据 55 String shuru = keyboard.nextLine(); 56 if("".equals(shuru) || shuru == null){ 57 flag = false; // 通过 嵌套if else 筛掉无用值 58 }else{ 59 if("end".equals(shuru)){ 60 flag = false; 61 }else{ 62 printStream.println(shuru); // 发送至服务端 63 printStream.flush(); 64 } 65 } 66 67 68 } 69 70 71 } catch (Exception e) { 72 // TODO: handle exception 73 } 74 75 76 } 77 78 public static void main(String[] args) { 79 80 try { 81 82 socket = new Socket("localhost",6789); 83 System.out.println("客户端已连接至服务端!"); 84 Get_Set(socket); 85 86 } catch (Exception e) { 87 // TODO: handle exception 88 System.out.println("客户端异常1"); 89 }finally { 90 try { 91 printStream.close(); 92 bufferedReader.close(); 93 socket.close(); 94 95 } catch (Exception e2) { 96 // TODO: handle exception 97 System.out.println("客户端异常2"); 98 } 99 }100 101 102 }103 104 105 }
好了 ,下面我们来运行 看看结结果。
第一个控制台是 服务端
第二个控制台是 客户端1
第三个控制台是 客户端2
这样我们就实现了 一个简单的基于TCP/IP协议的socket多客户端通信。
本文转自 sshpp 51CTO博客,原文链接:http://blog.51cto.com/12902932/1925685,如需转载请自行联系原作者