当前位置: 首页 > news >正文

UDP数据报和TCP流套接字编程

文章目录

    • UDP数据报套接字编程
      • 1.DatagramSocket类
      • 2.DatagramPacket类
      • 3. InetSocketAddress类
      • 构建服务端和客户端
    • TCP流套接字编程
      • 1. ServerSocket类
      • 2.Socket类
      • 构建服务端和客户端
    • 扩展
      • 对话形式
      • 简易的字典
      • 多线程实现
      • 线程池实现

UDP数据报套接字编程

1.DatagramSocket类

DatagramSocket 是UDP Socket,⽤于发送和接收UDP数据报。
DatagramSocket构造方法:
DatagramSocket():创建⼀个UDP数据报套接字的Socket,绑定到本机任意⼀个随机端⼝(⼀般⽤于客户端)
DatagramSocket(int port):创建⼀个UDP数据报套接字的Socket,绑定到本机指定的端⼝(⼀般⽤于服务端)
DatagramSocket方法:
void receive(DatagramPacket p):
从此套接字接收数据报(如果没有接收到数据报,该⽅法会阻塞等待)
void send(DatagramPacket p):从此套接字发送数据报(不会阻塞等待,直接发送)
void close():关闭此数据报

2.DatagramPacket类

DatagramPacket构造方法:
DatagramPacket(byte[] buf, int length):
构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)

DatagramPacket(byte[] buf, int offset, int length,SocketAddress address):构造⼀个DatagramPacket以⽤来发送数据报,发送的
数据为字节数组(第⼀个参数buf)中,从0到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP和端⼝号

DatagramPacket方法:
InetAddress getAddress():从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int getPort():从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号
byte[] getData():获取数据报中的数据

3. InetSocketAddress类

构造UDP发送的数据报时,需要传⼊ SocketAddress ,该对象可以使⽤ InetSocketAddress来创建。
InetSocketAddress ( SocketAddress 的⼦类 )构造⽅法:
InetSocketAddress(InetAddress addr, int port):创建一个Socket地址,包含IP地址和端口号

构建服务端和客户端

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;public class UDPEchosever {//创建服务端DatagramSocket socket;public UDPEchosever(int post) throws SocketException {if(post<1024||post>65535){throw new RuntimeException("端口号不符合条件");}socket=new DatagramSocket(post);}public void start() throws IOException {System.out.println("服务器已启动");while (true){//接收用户发来的数据DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);// 2. 接收数据socket.receive(requestPacket);// 3. 解析接收到的数据String request = new String(requestPacket.getData(), 0,requestPacket.getLength(), "UTF-8");//接收响应String respose=count(request);//发送响应DatagramPacket resposeSock=new DatagramPacket(respose.getBytes(StandardCharsets.UTF_8),0,respose.length(),requestPacket.getSocketAddress());socket.send(resposeSock);System.out.printf("[%s:%d] request :%s,response=%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,respose);}}public String count(String request){return request;}public static void main(String[] args) throws IOException {UDPEchosever udpEchosever=new UDPEchosever(8888);udpEchosever.start();}
}
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;public class UDPEchoclient {//创建客户端DatagramSocket socket;//定义端口号,IP地址String IP;int port;public UDPEchoclient (String IP,int port) throws SocketException {this.socket=new DatagramSocket();this.IP=IP;this.port=port;}public void start() throws IOException {System.out.println("客服端已启动");while (true){System.out.println("->");//发送内容Scanner scanner=new Scanner(System.in);String request=scanner.nextLine();if(request==null||request.isEmpty()){System.out.println("字符串不能为空");}//包装用户发送的内容//SocketAddress address = new InetSocketAddress(IP, port);DatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),0, request.getBytes().length, new InetSocketAddress(IP, port));
//            DatagramPacket datagramPacket=new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),0,request.length(),
//                    new InetSocketAddress(IP,port));socket.send(requestPacket);//用DatagramPacket接收服务器的响应数据DatagramPacket revicesocket=new DatagramPacket(new byte[1024],1024);socket.receive(revicesocket);//解析发送来的数据String respose=new String(revicesocket.getData(),0, revicesocket.getLength(),"UTF-8");System.out.printf("request:%s,repost:%s",request,respose);}}public static void main(String[] args) throws IOException {//System.out.println("你好");UDPEchoclient udpEchoclient=new UDPEchoclient("127.0.0.1",8888);udpEchoclient.start();}
}

在这里插入图片描述

TCP流套接字编程

1. ServerSocket类

ServerSocket 构造⽅法:
ServerSokcet(int port):创建⼀个服务端流套接字Socket,并绑定到指定端⼝
ServerSocket方法:
Socket accept():开始监听指定端⼝(创建时绑定的端⼝),有客⼾端连接后,返回⼀个服务端Socket对象,并基于该Socket建⽴与客⼾端的连接,否则阻塞等待
void close():关闭此套接字

2.Socket类

Socket 是客⼾端Socket,或服务端中接收到客⼾端建⽴连接(accept⽅法)的请求后,返回的服务端Socket。
不管是客⼾端还是服务端Socket,都是双⽅建⽴连接以后,保存的对端信息,及⽤来与对⽅收发数据的。
Socket的构造方法:
Socket(String host, int port):创建⼀个客⼾端流套接字Socket,并与对应IP的主机
上,对应端⼝的进程建⽴连接
Socket方法:
InetAddress getInetAddress() 返回套接字所连接的地址
InputStream getInputStream() 返回此套接字的输⼊流
OutputStream getOutputStream() 返回此套接字的输出流

构建服务端和客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TCPEchoSever {ServerSocket socket;//定义客户端public TCPEchoSever(int pase) throws IOException {if(pase<1024||pase>65535){System.out.println("端口号不符合条件");}this.socket=new ServerSocket(pase);}public void start() throws IOException {System.out.println("服务器已启动,等待客服端连接");//循环接收连接需求while (true){Socket clientsocket=socket.accept();//创建一个方法去接收客服端的内容reviceports(clientsocket);}}public void reviceports(Socket clientsocket) throws IOException {System.out.printf("[%s %d] 客服端上线了\n",clientsocket.getInetAddress().toString(),clientsocket.getPort());//使用输出流和输入流进行接收try(InputStream inputStream= clientsocket.getInputStream();OutputStream outputStream= clientsocket.getOutputStream()){while (true) {Scanner scanner = new Scanner(inputStream);//嵌入输入流if (!scanner.hasNextLine()) {System.out.printf("[%s %d] 客服端下线了",clientsocket.getInetAddress().toString(),clientsocket.getPort());break;}//获取用户发来的内容String request = scanner.nextLine();//对内容进行计算响应String respose = Calculation(request);//把响应写入输出流PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(respose);//刷新缓冲区printWriter.flush();//打印System.out.printf("[%s:%d] request=%s,respose=%s\n", clientsocket.getInetAddress().toString(), clientsocket.getPort(), request, respose);}}}protected String Calculation(String respose){return respose;}public static void main(String[] args) throws IOException {TCPEchoSever tcpEchoSever=new TCPEchoSever(8888);tcpEchoSever.start();}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TCPEchoClient {//创建客服端Socket socket;String IP;int port;public TCPEchoClient(String IP, int port) throws IOException {if (IP == null || IP.isEmpty()) {throw new RuntimeException("IP不能为空");}if (port < 1024 || port > 65535) {throw new RuntimeException("端口号不符合要求");}socket = new Socket(IP, port);}public void start() {System.out.println("客服端已启动");try (InputStream inputStream = this.socket.getInputStream();OutputStream outputStream = this.socket.getOutputStream()) {while (true) {Scanner scanner = new Scanner(System.in);String request = scanner.nextLine();if (request.isEmpty() || request == null) {System.out.println("发送内容不能为空");}PrintWriter printWriter = new PrintWriter(outputStream);//把数据写入输出流printWriter.println(request);printWriter.flush();//接收服务端发送来的数据Scanner scan = new Scanner(inputStream);String respose = scan.nextLine();System.out.println("request:" + request + "repose:" + respose);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {TCPEchoClient tcpEchoClient=new TCPEchoClient("127.0.0.1",8888);tcpEchoClient.start();}
}

扩展

连接的端口号自定义在1024-65535间,自己定义统一就行,都是在服务端修改,客服端不发生修改

对话形式

import java.io.IOException;
import java.util.Scanner;public class TCPEchoexchange extends TCPEchoSever {public TCPEchoexchange(int pase) throws IOException {super(pase);}@Overrideprotected String Calculation(String request) {//打印发送来的内容System.out.println(request);System.out.println("请用户输入回应内容");while (true){Scanner scanner=new Scanner(System.in);String respose=scanner.nextLine();if(respose==null||respose.isEmpty()){System.out.println("输入内容不能为空");}return respose;}}public static void main(String[] args) throws IOException {TCPEchoexchange tcpEchoexchange=new TCPEchoexchange(6666);tcpEchoexchange.start();}
}

简易的字典

import java.io.IOException;
import java.util.HashMap;public class TCPEchoMapsever  extends TCPEchoSever{HashMap<String,String> map;public TCPEchoMapsever(int pase) throws IOException {super(pase);map=new HashMap<>();map.put("狗","dog");map.put("猫","cat");map.put("鸡","chicken");map.put("猪","pig");}@Overrideprotected String Calculation(String request) {String key= map.getOrDefault(request,"没有找到");return key;}public static void main(String[] args) throws IOException {TCPEchoMapsever tcpEchoMapsever=new TCPEchoMapsever(8888);tcpEchoMapsever.start();}
}

多线程实现

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TCPchoThread extends TCPEchoSever{public TCPchoThread(int pase) throws IOException {super(pase);}@Overridepublic void start() throws IOException {System.out.println("服务端已启动");while (true){Socket client=socket.accept();Thread th = new Thread (()->{try {reviceports(client);} catch (IOException e) {throw new RuntimeException(e);}});th.start();}}public static void main(String[] args) throws IOException {TCPchoThread tcPchoThread=new TCPchoThread(9999);tcPchoThread.start();}

线程池实现

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TCPEchoPoolthread extends TCPEchoSever {public TCPEchoPoolthread(int pase) throws IOException {super(pase);}@Overridepublic void start() throws IOException {ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(4,10,1,TimeUnit.SECONDS,new ArrayBlockingQueue<>(2));System.out.println("服务端已启动,等待客服端连接");while (true){Socket client=socket.accept();threadPoolExecutor.submit(()->{try {reviceports(client);} catch (IOException e) {throw new RuntimeException(e);}});}}public static void main(String[] args) throws IOException {TCPEchoPoolthread tcpEchoPoolthread=new TCPEchoPoolthread(7777);tcpEchoPoolthread.start();}
}

相关文章:

  • 【网络原理】TCP异常处理(一):粘包问题
  • WSL2下Docker desktop的Cadvisor容器监控
  • 海思SD3403边缘计算AI核心设备概述
  • AI 边缘计算网关十大品牌
  • 高防CDN如何兼顾防护以及加速
  • 通用事件库IO多路复用技术选型与设计
  • MODSIM选型指南:汽车与航空航天企业如何选择仿真平台
  • 对 FormCalc 语言支持较好的 PDF 编辑软件综述
  • 基于蓝耘MaaS平台进行api调用创建本地智能ai
  • 【Web】如何解决 `npm run dev` 报错 `address already in use 127.0.0.1:9005` 的问题
  • Linux[配置vim]
  • 【工具】PDF转HTML
  • 第十六届蓝桥杯 2025 C/C++B组 第二轮省赛 全部题解(未完结)
  • leetcode 2516. 每种字符至少取 K 个
  • neo4j vs python
  • 小刚说C语言刷题——1032分糖果
  • 【今日三题】小红的ABC(找规律) / 不相邻取数(多状态dp) / 空调遥控(排序+二分/滑动窗口)
  • PLOT: PROMPT LEARNING WITH OPTIMAL TRANSPORT FOR VISION -LANGUAGE MODELS
  • Kafka 的服务端的物理存储架构是什么?零拷贝,mmap,sendfile、DMA gather又是什么?
  • Go语言中的错误处理
  • 民营经济促进法出台,自今年5月20日起施行
  • 农行一季度净利润719亿元增2.2%,不良率微降至1.28%
  • 商务部新闻发言人就波音公司飞回拟交付飞机答记者问
  • “杭州六小龙”的招聘迷局
  • 葡萄牙总理:未来几小时内将全面恢复供电
  • 中共中央、国务院关于表彰全国劳动模范和先进工作者的决定