JAVA-Socket通信笔记
JAVA - Socket
从开学到现在 也学了三个月时间的java了,一直在 在 语法和基本使用上周旋,井底之娃一枚。 这两天 有学长指点,花了两天的时间 学习了java多线程和socket的简单使用,利用周末时间 自己写了个 Socket 多客户端的 Demo,有很多不成熟或者不好的 地方,请指正。
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 exception 48 System.out.println("服务端异常1"); 49 }finally { 50 51 try { 52 socket.close(); 53 serverSocket.close(); 54 55 } catch (IOException e2) { 56 // TODO: handle exception 57 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 @Override 23 public void run() { 24 // TODO Auto-generated method stub 25 super.run(); 26 27 try { 28 Get_Set(socket); 29 30 } catch (Exception e) { 31 // TODO: handle exception 32 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 exception 68 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多客户端通信。
笔者 还是个 编程菜鸟,有什么不好的地方,希望各位大牛可以指正。