JAVA-Socket通信笔记

简介:

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 连接请求;

  1. 重复执行:

  • 调用 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,如需转载请自行联系原作者

相关文章
|
6天前
|
设计模式 Java
Java基础—笔记—多态、final、抽象类、接口篇
该文介绍了编程中的多态、final和抽象类、接口相关概念。多态允许子类重写父类方法,通过父类引用调用子类方法,实现解耦和提高代码灵活性,但也可能导致无法使用子类特有功能,需通过强制类型转换解决。final用于修饰不可变的类、方法或变量,防止继承、重写和多次赋值。抽象类是一种包含抽象方法的类,用于强制子类重写特定方法,实现多态,适用于模板方法设计模式,解决代码重复问题。
22 0
|
6天前
|
Java
Java基础—笔记—static篇
`static`关键字用于声明静态变量和方法,在类加载时初始化,只有一份共享内存。静态变量可通过类名或对象访问,但推荐使用类名。静态方法无`this`,不能访问实例成员,常用于工具类。静态代码块在类加载时执行一次,用于初始化静态成员。
13 0
|
6天前
|
Java API 索引
Java基础—笔记—String篇
本文介绍了Java中的`String`类、包的管理和API文档的使用。包用于分类管理Java程序,同包下类无需导包,不同包需导入。使用API时,可按类名搜索、查看包、介绍、构造器和方法。方法命名能暗示其功能,注意参数和返回值。`String`创建有两种方式:双引号创建(常量池,共享)和构造器`new`(每次新建对象)。此外,列举了`String`的常用方法,如`length()`、`charAt()`、`equals()`、`substring()`等。
17 0
|
6天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
6天前
|
网络协议 算法 Java
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
19 3
|
2天前
|
Java
Java一分钟之-并发编程:线程间通信(Phaser, CyclicBarrier, Semaphore)
【5月更文挑战第19天】Java并发编程中,Phaser、CyclicBarrier和Semaphore是三种强大的同步工具。Phaser用于阶段性任务协调,支持动态注册;CyclicBarrier允许线程同步执行,适合循环任务;Semaphore控制资源访问线程数,常用于限流和资源池管理。了解其使用场景、常见问题及避免策略,结合代码示例,能有效提升并发程序效率。注意异常处理和资源管理,以防止并发问题。
25 2
|
6天前
|
XML JSON 网络协议
Socket实现模拟TCP通信粘包问题
Socket实现模拟TCP通信粘包问题
|
6天前
|
Java 开发者 Spring
Java一分钟之-Java网络编程基础:Socket通信
【5月更文挑战第13天】本文介绍了Java Socket编程基础知识,包括使用`ServerSocket`和`Socket`类建立连接,通过`OutputStream`和`InputStream`进行数据传输。常见问题涉及忘记关闭Socket导致的资源泄漏、网络异常处理及并发同步。理解Socket通信原理并掌握异常处理、资源管理和并发控制,能帮助开发者构建更稳定的网络应用。
31 1
|
6天前
|
网络协议 Java 网络安全
【计算机网络】—— Socket通信编程与传输协议分析
【计算机网络】—— Socket通信编程与传输协议分析
15 0
|
6天前
|
网络协议 Java
Java中如何使用Socket类检测端口是否存在
Java中如何使用Socket类检测端口是否存在
28 4