1. TCP通信

1.1. Socket通讯模型

1.1.1. Server端多线程模型

通过上一节我们已经知道了如何使用ServerSocket与Socket进行通讯了,但是这里存在着一个问题,就是只能“p2p”点对点。一个服务端对一个客户端。若我们想让一个服务端可以同时支持多个客户端应该怎么做呢?这时我们需要分析之前的代码。我们可以看到,当服务端的ServerSocket通过accept方法侦听到一个客户端Socket连接后,就获取该Socket并与该客户端通过流进行双方的通讯了,这里的问题在于,只有不断的调用accept方法,我们才能侦听到不同客户端的连接。但是若我们循环侦听客户端的连接,又无暇顾及与连接上的客户端交互,这时我们需要做的事情就是并发。我们可以创建一个线程类ClientHandler,并将于客户端交互的工作全部委托线程来处理。这样我们就可以在当一个客户端连接后,启动一个线程来负责与客户端交互,而我们也可以循环侦听客户端的连接了。

我们需要对服务端的代码进行修改:

copytextpop-up

  1. /**
  2. * Server端应用程序*
  3. */
  4. public class Server {
  5.     public static void main(String[] args) {
  6.         ServerSocket server = null;
  7.         try {
  8.             //创建ServerSocket并申请服务端口为8088
  9.             server = new ServerSocket(8088);
  10.             
  11.             while(true){
  12.                 //循环侦听客户端的连接
  13.                 Socket socket = server.accept();
  14.                 //当一个客户端连接后,启动线程来处理该客户端的交互
  15.                 new ClientHandler(socket).start();
  16.             }
  17.         } catch (Exception e) {
  18.             e.printStackTrace();
  19.         } finally{
  20.             if(server != null){
  21.                 try {
  22.                     server.close();
  23.                 } catch (IOException e) {
  24.                 }
  25.             }
  26.         }
  27.     }
  28. }
  29. /**
  30. * 线程类
  31. * 该线程的作用是并发与客户端进行交互
  32. * 这里的代码就是原来在Server中客户端连接后交互的代码
  33. */
  34. class ClientHandler extends Thread{
  35.     private Socket socket;
  36.     public ClientHandler(Socket socket){
  37.         this.socket = socket;
  38.     }
  39.     public void run(){
  40.         try {
  41.             //获取输入流,用于读取客户端发送过来的消息
  42.             InputStream in = socket.getInputStream();
  43.             BufferedReader reader
  44.                 = new BufferedReader(
  45.                     new InputStreamReader(
  46.                         in,"UTF-8"
  47.                     )
  48.                 );
  49.             
  50.             //获取输出流,用于向该客户端发送消息
  51.             OutputStream out = socket.getOutputStream();
  52.             PrintWriter writer
  53.                 = new PrintWriter(
  54.                     new OutputStreamWriter(
  55.                         out,"UTF-8"    
  56.                     ),true
  57.                 );
  58.             
  59.             //读取客户端发送的消息
  60.             String message = reader.readLine();
  61.             System.out.println("客户端说:"+message);
  62.             
  63.             //向客户端发送消息
  64.             writer.println("你好客户端!");
  65.         } catch (Exception e) {
  66.             e.printStackTrace();
  67.         }
  68.     }
  69. }
/***  Server端应用程序**/
public class Server {public static void main(String[] args) {ServerSocket server = null;try {//创建ServerSocket并申请服务端口为8088server = new ServerSocket(8088);while(true){//循环侦听客户端的连接Socket socket = server.accept();//当一个客户端连接后,启动线程来处理该客户端的交互new ClientHandler(socket).start();}} catch (Exception e) {e.printStackTrace();} finally{if(server != null){try {server.close();} catch (IOException e) {}}}}
}
/*** 线程类* 该线程的作用是并发与客户端进行交互* 这里的代码就是原来在Server中客户端连接后交互的代码*/
class ClientHandler extends Thread{private Socket socket;public ClientHandler(Socket socket){this.socket = socket;}public void run(){try {//获取输入流,用于读取客户端发送过来的消息InputStream in = socket.getInputStream();BufferedReader reader= new BufferedReader(new InputStreamReader(in,"UTF-8"));//获取输出流,用于向该客户端发送消息OutputStream out = socket.getOutputStream();PrintWriter writer= new PrintWriter(new OutputStreamWriter(out,"UTF-8"  ),true);//读取客户端发送的消息String message = reader.readLine();System.out.println("客户端说:"+message);//向客户端发送消息writer.println("你好客户端!");} catch (Exception e) {e.printStackTrace();}}
}

经过上面的改动,我们再次启动服务端,这个时候我们会发现,我们启动若干客户端都可以被服务器所接受并进行交互了。

2. UDP通信

2.1. DatagramPacket

2.1.1. 创建接收包

DatagramPacket:UDP数据报基于IP建立的,每台主机有65536个端口号可以使用。数据报中字节数限制为65536-8 。包含8字节的头信息。

构造接收包:

copytextpop-up

  1.     DatagramPacket(byte[] buf, int length)
   DatagramPacket(byte[] buf, int length)

将数据包中Length长的数据装进Buf数组。

copytextpop-up

  1.     DatagramPacket(byte[] buf, int offset, int length)
    DatagramPacket(byte[] buf, int offset, int length)

将数据包中从Offset开始、Length长的数据装进Buf数组。

2.1.2. 创建发送包

构造发送包:

copytextpop-up

  1.     DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort)
   DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort)

从Buf数组中,取出Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。

copytextpop-up

  1.     DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort)
   DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort)

从Buf数组中,取出Offset开始的、Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。

2.2. DatagramSocket

2.2.1. 服务端接收

DatagramSocke用于接收和发送UDP的Socket实例 。

copytextpop-up

  1.     DatagramSocket(int port)
 DatagramSocket(int port)

创建实例,并固定监听Port端口的报文。通常用于服务端。

其中方法:

copytextpop-up

  1.      receive(DatagramPacket d)
    receive(DatagramPacket d)

接收数据报文到d中。receive方法产生 “阻塞”。会一直等待知道有数据被读取到。

2.2.2. 客户端发送

无参的构造方法DatagramSocket()通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。程序会让操作系统分配一个可用的端口。

其中方法:

copytextpop-up

  1.     send(DatagramPacket dp)
 send(DatagramPacket dp)

该方法用于发送报文dp到目的地。

代码如下:

copytextpop-up

  1.     /**
  2.      * Server端程序
  3.      */
  4.     public class Server {
  5.     public static void main(String[] args) {
  6.         DatagramSocket socket = null;
  7.         try {
  8.             socket = new DatagramSocket(8088);//申请8088端口
  9.             byte[] data = new byte[1024];
  10.             DatagramPacket packet
  11.                 = new DatagramPacket(data, data.length);//创建接收包
  12.             socket.receive(packet);//会产生阻塞,读取发送过来的数据
  13. String str = new String(packet.getData(),0,packet.getLength());//从 包中取数据
  14.             System.out.println(str);
  15.             
  16.         } catch (Exception e) {
  17.             e.printStackTrace();
  18.         } finally{
  19.             if(socket != null){
  20.                 socket.close();//关闭释放资源
  21.             }
  22.         }
  23.     }
  24. }
  25. /**
  26. * Client端程序
  27. */
  28. public class Client {
  29.     public static void main(String[] args) {
  30.         DatagramSocket socket = null;
  31.         try {
  32.             socket = new DatagramSocket();//创建Socket
  33.             byte[] data = "你好服务器!".getBytes();
  34.             DatagramPacket packet = new DatagramPacket(
  35.                                         data,
  36.                                         data.length,
  37.                                         InetAddress.getByName("localhost"),
  38.                                         8088
  39.                                     );//创建发送包
  40.             socket.send(packet);//发送数据
  41.             
  42.             
  43.         } catch (Exception e) {
  44.             e.printStackTrace();
  45.         } finally{
  46.             if(socket != null){
  47.                 socket.close();//关闭以释放资源
  48.             }
  49.         }
  50.     }
  51. }
    /***  Server端程序*/public class Server {public static void main(String[] args) {DatagramSocket socket = null;try {socket = new DatagramSocket(8088);//申请8088端口byte[] data = new byte[1024];DatagramPacket packet= new DatagramPacket(data, data.length);//创建接收包socket.receive(packet);//会产生阻塞,读取发送过来的数据String str = new String(packet.getData(),0,packet.getLength());//从包中取数据System.out.println(str);} catch (Exception e) {e.printStackTrace();} finally{if(socket != null){socket.close();//关闭释放资源}}}
}
/***  Client端程序*/
public class Client {public static void main(String[] args) {DatagramSocket socket = null;try {socket = new DatagramSocket();//创建Socketbyte[] data = "你好服务器!".getBytes();DatagramPacket packet = new DatagramPacket(data, data.length,InetAddress.getByName("localhost"),8088);//创建发送包socket.send(packet);//发送数据} catch (Exception e) {e.printStackTrace();} finally{if(socket != null){socket.close();//关闭以释放资源}}}
}

TCP通信 、 UDP通信相关推荐

  1. Android Wifi连接控制、TCP、UDP通信,6.0以上适配

    本文章包含内容 Wifi连接控制.Wifi广播接收,适配了Android6.0以上的版本 Wifi下的TCP通信 Wifi下的UDP通信 Github项目地址 码云项目地址 最近公司要开发智能家居,A ...

  2. [python学习] 专题七.网络编程之套接字Socket、TCP和UDP通信实例

    很早以前研究过C#和C++的网络通信,参考我的文章:                  C#网络编程之Tcp实现客户端和服务器聊天                 C#网络编程之套接字编程基础知识   ...

  3. 高性能 TCP amp; UDP 通信框架 HP-Socket v3.2.3 正式宣布

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包括服务端组件.client组件和 Agent 组件.广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#. ...

  4. 网络通信、UDP通信、TCP通信、BS架构模拟、URL了解

    网络编程 网络通信 网络通信三要素之IP地址(了解) JAVA对IP地址的操作(InetAddress类) 网络通信三要素之端口号(了解) 网络通信三要素之协议(了解) UDP通信 UDP通信之广播和 ...

  5. Socket之UDP通信

    Socket之UDP通信 UDP通信原理: UDP协议是一种不可靠的网络协议,它在通信两端各自建立一个Socket对象,但是这两个Socket对象只是发送和接收数据的对象,因此基于UDP协议的通信双方 ...

  6. 40 张图带你搞懂 TCP 和 UDP

    前言 拿下计网协议后,我就是公园里最靓的仔 TCP/IP 基础知识总结 计算机网络基础知识总结 那么下面就开始我们本篇文章,文章组织脉络如下 运输层位于应用层和网络层之间,是 OSI 分层体系中的第四 ...

  7. 【网络通信与信息安全】之深入解析TCP与UDP传输协议

    一.什么是 socket ? Socket 的英文原义是"孔"或"插座".在编程中,Socket 被称做套接字,是网络通信中的一种约定.Socket 编程的应用 ...

  8. 【STM32+cubemx】0020 HAL库开发:以太网ENC28J60芯片和TCP、UDP简单应用

    MCU通过以太网通信有很多种方式,有的内部自带以太网接口(如stm32f107的某些型号):如果没有,也可以在外围连接以太网芯片来实现.外接的以太网芯片,又分为带网络协议栈和不带协议栈的,带网络协议栈 ...

  9. [Unity Mirror] TCP 和 UDP

      TCP 和 UDP 都是用于通过 Internet 发送信息的协议 - 事实上,它们是世界上最常用的两种 Internet 协议:TCP 是在 1970 年代开发的,而 UDP 是在 1980 年 ...

  10. TCP/IP协议学习笔记(二)TCP与UDP介绍

    TCP/IP中有两个具有代表性的传输层协议,它们分别是TCP和UDP.TCP提供可靠的通信传输,而UDP则常被用于让广播和细节控制交给应用的通信传输. IP首部中有一个协议字段,用来标识网络层(IP) ...

最新文章

  1. [翻译] Ruby Golf
  2. 博士补贴125万,硕士70万本科21万,浙江某地人才(简直是抢人)新政!
  3. let const var 比较说明
  4. 深入理解正则表达式环视的概念与用法
  5. Oracle procedure调用实例
  6. PowerBuilder窗口之间传递多参数的方法
  7. 翻译软件(用百度的API实现)Python
  8. java导出pdf集合_java实现导出pdf-Go语言中文社区
  9. makemid+matlab,《MATLAB基础》双语课
  10. 工业以太网交换机的优势以及注意事项介绍
  11. 背景纹理素材|为前景元素添加焦点
  12. hdu 3631 Shortest Path(Floyd)
  13. 丛铭俣 160809324 (作业5)
  14. 关关php采集插件,推荐使用:关关采集器(杰奇全版本通用编码版)v3.5.00
  15. 阿里中台搞了3年,搞砸了?网传:副总裁玄难“背锅”,辞职创业!
  16. 关于创建String对象的抉择
  17. ffmpeg生成的视频与QuickTime不兼容
  18. D. Lizard Era: Beginning
  19. [RK3288][Android6.0] 主动从WLAN网络切换到移动数据网络
  20. keep-alive用法

热门文章

  1. clear:both的认知
  2. 大数运算(高精度运算)
  3. setTimeout函数的参数
  4. 特征工程 特征选择 reliefF算法
  5. 进程管理 进程的调度
  6. 读取云服务器文件列表,读取云服务器文件列表
  7. android9.0官方壁纸,谷歌出品:安卓9.0原生春天主题壁纸 每一张都是谷歌的精挑细选!...
  8. 动态规划之线性动态规划
  9. React-signature-phone 移动端电子签名
  10. JMS介绍:我对JMS的理解和认识