【计算机网络原理】网络编程和Socket套接字

server/2024/9/20 7:27:29/ 标签: 计算机网络, 网络

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶​
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客

系列专栏:xiaoxie的网络>计算机网络学习系列专栏——CSDN博客●'ᴗ'σσணღ
我的目标:"团团等我💪( ◡̀_◡́ ҂)" 

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)!

目录

一.网络编程

1.什么是网络编程

2.网络编程中的基本概念

1.发送端 vs 接收端

​编辑 2.客户端vs服务端

3.请求 vs 响应

 二.Socket套接字

1.概念

2.分类

1.流套接字:基于传输层TCP协议

2.数据报套接字:基于传输层UDP协议

其中UDP的特点为:

3.简单的对比一下UDP协议和TCP协议

3.Java数据报套接字通信模型

1.对于⼀次发送及接收UDP数据报的流程如下:

 ​编辑

2.提供多个客⼾端的请求处理及响应,流程如下:

3.TCP的简单模型

​编辑

4..UDP数据报套接字编程

1.UdpEchoClient 类(客户端)

2.UdpEchoServe 类(服务器端)

3.主函数

4.交互过程

5.TCP数据报套接字编程

1.TcpEchoServe 类(服务器端)

2.TcpEchoClient 类(客户端)

3.主函数

4.交互过程

5.解释一下这里为什么要用scanner以及为什么要加换行符 \n

1.使用 Scanner 的原因:

2.加入换行符 \n 的原因:

3.注意事项:


一.网络编程

1.什么是网络编程

是指网络上的主机,通过不同的进程以编程的⽅式实现⽹络通信.

 当然,我们也可以是在一台主机,只要是在不同的进程中,就可以通过网络通信来传输资源,不一定需要在多台主机上实现.同时并不代表只能是从进程B进程A,而是从发送方,到接收方,进程A可以是发送方,也可以是接收方,进程B同理.

2.网络编程中的基本概念

1.发送端 vs 接收端

在⼀次⽹络数据传输时:
发送端:数据的发送⽅进程,称为发送端。发送端主机即⽹络通信中的源主机。
接收端:数据的接收⽅进程,称为接收端。接收端主机即⽹络通信中的⽬的主机。
收发端:发送端和接收端两端,也简称为收发端。
注意:发送端和接收端只是相对的,只是⼀次⽹络数据传输产⽣数据流向后的概念。

 2.客户端vs服务端

服务端:服务端通常是一个长期的、稳定的进程,它等待客户端的请求并提供相应的服务或数据。

客户端:获取服务的一方进程,称为客⼾端。

交互方式:
  • 请求-响应模式客户端向服务端发送请求,服务端处理请求后返回响应。这是最常见的交互模式。
  • 推送模式服务端也可以主动向客户端推送信息,但这种情况较少见,通常用于实时通信或通知。例如我们使用手机时,像一些什么新闻的APP的后台(服务端),就会时不时的给我们(客户端)发送一些热点新闻的推送,或者是我们微信接收信息也可以说是,服务端给我们推送消息.

 网络编程中的角色

  • 网络编程中,开发者需要同时考虑客户端和服务端的实现。服务端的实现更注重稳定性、性能和安全性,而客户端的实现则更注重用户体验和界面设计。

分布式系统:

在分布式系统中,客户端和服务端的概念可以更加复杂。一个系统可能包含多个服务端,它们之间通过内部通信协同工作,共同为客户端提供服务

总的来说,服务端和服务端在网络通信中扮演着不同的角色,它们通过网络协议相互协作,共同为用户提供服务。理解客户端和服务端的区别和联系,对于设计和实现网络应用非常重要。 

3.请求 vs 响应

 请求:请求是客户端(如浏览器、服务器或其他客户端程序)发送给服务端的一条消息,请求服务端执行某项操作或提供某些数据。

响应:响应是服务端对客户端请求的答复。服务端处理完请求后,会返回一个响应消息,告知客户端操作的结果或提供请求的数据。

 二.Socket套接字

1.概念

Socket套接字,是由系统提供⽤于⽹络通信的技术,是基于TCP/IP协议的⽹络通信的基本操作单元。 基于Socket套接字的⽹络程序开发就是⽹络编程。见到这个词就可以认为是,"网络编程API"的统称.

2.分类

Socket套接字主要针对传输层协议划分为如下三类:

1.流套接字:基于传输层TCP协议

其中TCP的特点为:

1.有连接

2.可靠传输

3.面向字节流

4.全双工

对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是⽆边界的数据,可以多次发送,也可以分开多次接收。

2.数据报套接字:基于传输层UDP协议

其中UDP的特点为:

1. 无连接

2.不可靠传输

3.面向数据报

4.全双工

对于数据报来说,可以简单的理解为,传输数据是⼀块⼀块的,发送⼀块数据假如100个字节,必须⼀ 次发送,接收也必须⼀次接收100个字节,⽽不能分100次,每次接收1个字节。

3.简单的对比一下UDP协议和TCP协议

这只是简单对比,后续的详细的解释,在后面文章在展示

1.有连接 vs 无连接

  • 建立连接:在数据传输之前,通信双方必须建立一个连接。这通常涉及到一个建立连接的过程,如TCP协议中的三次握手。
  • 无连接:在数据传输之前,通信双方不需要建立连接。每个数据包(或称为数据报)独立发送。

 2.不可靠传输 vs 可靠传输

  • 不可靠传输:指的是在数据传输过程中,不保证数据包的完整性、顺序性或及时性。发送方发送数据后,无法确保数据包是否能够到达接收方,或者数据包是否按发送顺序到达。
  • 可靠传输:指的是在数据传输过程中,尽可能的确保数据包正确、完整、按顺序地到达接收方。如果数据在传输过程中出现丢失、错误或乱序,可靠传输机制会采取措施进行恢复

 3.面向字节流 vs面向数据报

  1. 面向字节流(Stream-oriented)

    • 数据被视为一个连续的字节序列,无边界。
    • 通常用于需要可靠传输的应用,如文件传输和网页浏览。
    • 例子:TCP(传输控制协议)。
  1. 面向数据报(Datagram-oriented)

    • 数据被分割成独立的数据报,每个数据报有明确边界。
    • 适用于对实时性要求高的应用,如在线游戏和VoIP。
    • 例子:UDP(用户数据报协议)。

选择面向字节流还是面向数据报的通信方式,取决于应用程序的具体需求。如果数据的可靠性和顺序性至关重要,面向字节流的通信方式(如TCP)是更好的选择。如果实时性和性能更为关键,面向数据报的通信方式(如UDP)可能更合适。在实际应用中,开发者需要根据应用的特点和需求,权衡可靠性、实时性、资源消耗等因素,选择合适的通信方式。 

4. 全双工

全双工是指在通信中,发送和接收可以同时进行,即两端的通信实体可以在同一时刻进行发送和接收操作,无需轮流占用通信线路。这种通信方式允许数据在两个方向上独立、连续地流动,从而提高了通信效率。

3.Java数据报套接字通信模型

对于UDP协议来说,具有⽆连接,⾯向数据报的特征,即每次都是没有建⽴连接,并且⼀次发送全部
数据报,⼀次接收全部的数据报。
java中使⽤UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使⽤
DatagramPacket 作为发送或接收的UDP数据报

1.对于⼀次发送及接收UDP数据报的流程如下:

 

  1. 发送端 (客户端)

    • 构建DatagramPacket:在发送UDP数据报之前,客户端需要构建一个DatagramPacket对象。这个对象将包含要发送的数据,以及接收方的IP地址和端口号。
  2. 接收端 (服务端)

    • 构建DatagramSocket:服务端需要构建一个DatagramSocket,这个套接字会绑定到一个端口上,监听到来的数据报。
    • 接收UDP数据报:服务端使用DatagramSocket来接收客户端发送的UDP数据报。在接收数据报时,DatagramSocket会阻塞,直到有数据报到达。
  3. DatagramPacket对象

    • 发送端的DatagramPacket包含要发送的数据(以byte数组的形式),以及接收方的IP地址和端口号。
    • 接收端的DatagramPacket在接收数据前是一个空对象,它将被用来填充接收到的数据,以及发送方的IP和端口号。
  4. 发送和接收过程

    • 发送端使用socket.send(packet)方法发送填充好的DatagramPacket
    • 接收端调用socket.receive(packet)方法,传入一个空的DatagramPacket对象,该对象在接收到数据后会被更新。
以上只是⼀次发送端的UDP数据报发送,及接收端的数据报接收,并没有返回的数据。也就是只有请
求,没有响应。对于⼀个服务端来说,重要的是

2.提供多个客⼾端的请求处理及响应,流程如下:

  1. 发送端 (客户端)

    • 构建DatagramSocket:用于发送UDP数据报。
    • 构建DatagramPacket:包含要发送的数据(byte数组)、目标IP地址和端口号。
    • socket.send(packet):通过DatagramSocket发送DatagramPacket
  2. 接收端 (服务端)

    • 构建DatagramSocket:用于接收UDP数据报,并绑定到一个端口上。
    • socket.receive(packet):使用DatagramSocket接收数据报,该方法会阻塞直到数据报到达。服务端需要提供一个空的DatagramPacket对象来接收数据。
    • 更新DatagramPacket:一旦接收到数据,DatagramPacket对象会被更新,包含接收到的数据以及发送方的IP地址和端口号。
  3. 通信过程

    • 客户端发送一个UDP数据报(请求)给服务端。
    • 服务端接收到数据报后,根据接收的数据执行业务逻辑。
    • 服务端根据业务逻辑的需要,可能需要发送一个UDP数据报(响应)回客户端。
    • 客户端接收到响应后,根据响应数据执行下一步的业务。
  4. 注意点

    • socket.receive(packet)方法会阻塞,直到从网络中收到一个数据报或者发生超时。
    • UDP是无连接的协议,不保证数据的可靠传输,不保证数据包的顺序,也不提供拥塞控制

3.TCP的简单模型

  1. 服务端(Server)

    • 创建ServerSocket:服务端首先创建一个ServerSocket对象,该对象绑定到一个特定的端口上并监听客户端的连接请求。
    • accept()方法:服务端调用ServerSocketaccept()方法,该方法会阻塞,直到有客户端发起连接请求。
  2. 客户端(Client)

    • 创建Socket:客户端创建一个Socket对象,指定服务端的IP地址和服务端监听的端口号。
    • 向服务端发起请求:客户端通过Socket对象向服务端发起连接请求。
  3. 建立连接

    • 一旦服务端的ServerSocket通过accept()方法接受到连接请求,就会创建一个新的Socket对象来与客户端建立通信。
    • 此时,服务端和客户端都拥有一个Socket对象,它们可以通过这个Socket对象进行通信。
  4. 通信过程

    • InputStreamOutputStream:服务端和客户端的Socket对象都提供了InputStreamOutputStream,用于双向通信。
    • 客户端和服务端可以通过OutputStream写入数据到对方,并通过InputStream读取来自对方的数据。
  5. 结束通信

    • 通信完成后,双方需要关闭它们的Socket对象以及相关的InputStreamOutputStream,以释放网络资源。
  6. 关闭资源

    • 服务端和客户端都应确保在通信结束时调用close()方法来关闭SocketInputStreamOutputStream,以避免资源泄露。

     7.注意:

            这里的建立连接和断开连接只是简单介绍,在TCP协议中,一个连接的建立通常遵循三次握              手过程,而在通信结束后,双方可以通过四次握手来优雅地关闭连接.这里就不展开说明了,

            后续会对这个进行详细的介绍和解释

4..UDP数据报套接字编程

结合上图我们就可以自己写一个简单的只是回显字符串的服务器和客户端了

服务端:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServe {private DatagramSocket socket = null;public UdpEchoServe(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while(true){//1.接收请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket);//从客服端接收请求,如果没有请求,即阻塞等待//将请求解析成字符串String request = new String(requestPacket.getData(),0, requestPacket.getLength());//经过process方法计算请求得出响应String response = this.process(request);//将响应传给客服端DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,requestPacket.getAddress(), requestPacket.getPort());socket.send(responsePacket);System.out.printf("[%s:%d],req = %s,resp = %s\n",requestPacket.getAddress(),requestPacket.getPort(),request,response);}}//这个请求的响应为回显public String process(String request) {return request;}public static void main(String[] args) throws IOException{UdpEchoServe udpEchoServe = new UdpEchoServe(8023);//这个端口号可以自己自定义,建议写1024以上的发展被占用udpEchoServe.start();}
}


客户端 

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serveIp;private int servePort;public UdpEchoClient(String serveIp,int servePort) throws SocketException {socket = new DatagramSocket(0);this.serveIp = serveIp;this.servePort = servePort;}public void start() throws IOException {System.out.println("客服端启动");Scanner scanner = new Scanner(System.in);while (true) {//输入请求System.out.println("请输入你要发送的请求:");String request = scanner.next();//将请求封装成数据报DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),0,request.getBytes().length,InetAddress.getByName(serveIp),servePort);//发送请求socket.send(requestPacket);//接收响应,因为接收的是数据报,所以要先创建一个数据报DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//将这个接收的数据报转化为字符串String response = new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1",8023);udpEchoClient.start();}}

结果如下图

以下是对这两个类的功能和它们之间交互的总结:

1.UdpEchoClient 类(客户端)
  1. 构造函数:创建一个 DatagramSocket 并在构造时绑定到一个随机端口(0)。
  2. start 方法
    • 客户端启动并进入一个无限循环。
    • 使用 Scanner 从标准输入读取用户输入的请求字符串。
    • 将请求字符串封装进 DatagramPacket 对象,并指定服务器的 IP 地址和端口号。
    • 使用 socket.send() 方法发送请求数据报到服务器。
    • 创建一个空的 DatagramPacket 对象用于接收响应,并通过 socket.receive() 方法阻塞等待服务器的响应。
    • 将接收到的响应数据报转换为字符串并打印出来。
2.UdpEchoServe 类(服务器端)
  1. 构造函数:创建一个 DatagramSocket 并绑定到指定的端口(例如 8023)。
  2. start 方法
    • 服务器启动并进入一个无限循环。
    • 创建一个空的 DatagramPacket 对象用于接收客户端的请求,并通过 socket.receive() 方法阻塞等待客户端的请求。
    • 将接收到的请求数据报转换为字符串。
    • 调用 process() 方法处理请求,由于是回显服务器,它简单地将请求字符串作为响应返回。
    • 将响应字符串封装进一个新的 DatagramPacket 对象,并发送回客户端。
    • 打印出请求和响应的信息,包括客户端的 IP 地址、端口号、请求内容和响应内容。
3.主函数
  • UdpEchoClient 的 main 方法:创建 UdpEchoClient 实例并启动客户端。
  • UdpEchoServe 的 main 方法:创建 UdpEchoServe 实例并启动服务器。
4.交互过程
  1. 服务器启动并监听指定端口,等待客户端请求。
  2. 客户端启动并提示用户输入请求,然后将请求发送给服务器。
  3. 服务器接收到请求后,将其作为响应发送回客户端。
  4. 客户端接收到响应并打印出来,然后等待下一次请求。

这个简单的 UDP 回显客户端和服务器示例展示了 UDP 协议的基本使用,包括数据报的发送和接收。UDP 协议的特点是无连接、低延迟,但不保证数据的可靠传输。

5.TCP数据报套接字编程

服务端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServe {private ServerSocket socket = null;public TcpEchoServe(int port) throws IOException{socket = new ServerSocket(port);}public void start() throws IOException{System.out.println("服务器启动");//接收客户端的请求ExecutorService poll = Executors.newCachedThreadPool();while(true) {Socket clintSocket = socket.accept();
//不使用线程池而是就使用多线程
//            Thread t = new Thread(()-> {
//                //建立连接
//                try {
//                    connectClint(clintSocket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            t.start();poll.submit(new Runnable() {@Overridepublic void run() {try {connectClint(clintSocket);} catch (IOException e) {throw new RuntimeException(e);}}});}}public void connectClint(Socket clintSocket) throws IOException{//打印一个日志告知服务器客户端连接上了System.out.printf("[%s:%d,客服端上线\n",clintSocket.getInetAddress(),clintSocket.getPort());//使用字节流的方式来传输数据try(InputStream clintInput = clintSocket.getInputStream();OutputStream clintOutput = clintSocket.getOutputStream()) {Scanner scanner = new Scanner(clintInput);//客服端每次和服务端连接有可能有多个请求while(true) {//如果后续没有数据了,就说明断开连接了if(!scanner.hasNext()) {System.out.printf("[%s:%d,客服端下线\n",clintSocket.getInetAddress(),clintSocket.getPort());break;}String result = scanner.next();//把等到的请求,进行分析计算返回给响应String response = process(result);//把响应输出给客服端clintOutput.write(response.getBytes(),0,response.getBytes().length);//服务器打印结果日志System.out.printf("%s:%d] req=%s, resp=%s\n",clintSocket.getInetAddress(),clintSocket.getPort(),result,response);}}catch (IOException e) {e.printStackTrace();}finally {clintSocket.close();}}public String process(String result) {//给响应这里后面加上一个换行符, 使客户端读取响应的时候, 也有明确的分隔符return result + "\n";}public static void main(String[] args) throws IOException{TcpEchoServe tcpEchoServe = new TcpEchoServe(8023);tcpEchoServe.start();}
}

 客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serveIp,int servePort)throws IOException {//和服务端连接socket = new Socket(serveIp,servePort);}public void start(){System.out.println("服务器启动!");Scanner scanner = new Scanner(System.in);//从服务端读取数据和输入数据try(InputStream serveInput = socket.getInputStream();OutputStream serveOutput = socket.getOutputStream()) {//从服务端接收数据Scanner serveScanner = new Scanner(serveInput);while (true){System.out.println("输入你要传输的数据");String result = scanner.next();//加换行result += "\n";//将数据传输给客服端serveOutput.write(result.getBytes(), 0, result.getBytes().length);if (!serveScanner.hasNext()) {break;}String response = serveScanner.next();System.out.println(response);}}catch (IOException e) {e.printStackTrace();}}public static void main(String[] args)throws IOException {TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",8023);tcpEchoClient.start();}
}

 结果:

1.TcpEchoServe 类(服务器端)
  1. 构造函数:创建并绑定一个 ServerSocket 到指定端口,监听客户端的连接请求。

  2. start 方法

    • 服务器启动并进入一个无限循环,等待客户端的连接请求。
    • 使用 socket.accept() 方法接受客户端的连接请求,该方法会阻塞直到有客户端连接。
    • 使用 Executors.newCachedThreadPool() 创建线程池,为每个客户端连接创建新线程处理。
    • 调用 connectClint() 方法处理与客户端的连接。
  3. connectClint 方法

    • 打印客户端上线日志。
    • 创建 InputStream 和 OutputStream 对客户端进行读写操作。
    • 使用 Scanner 从输入流中读取客户端发送的数据。(阻塞等待)
    • 如果读取到数据,通过 process() 方法处理数据(在这里是简单的回显)。
    • 将处理后的数据写入输出流,发送回客户端。
    • 打印请求和响应日志。
    • 当客户端断开连接或发生异常时,关闭 Socket 并打印客户端下线日志。
2.TcpEchoClient 类(客户端)
  1. 构造函数:创建一个 Socket 对象,尝试连接到指定IP地址和端口的服务端。
  2. start 方法
    • 客户端启动并进入一个无限循环。
    • 使用 Scanner 从标准输入读取用户输入的数据。
    • 将用户输入的数据发送到服务端,数据后添加了换行符 \n 作为分隔符。
    • 创建 InputStream 和 OutputStream 对服务端进行读写操作。
    • 从服务端的输入流中读取响应数据,并打印出来。
    • 如果服务端关闭连接,循环结束。
3.主函数
  • TcpEchoServe 的 main 方法:创建 TcpEchoServe 实例并启动服务器。
  • TcpEchoClient 的 main 方法:创建 TcpEchoClient 实例并启动客户端。
4.交互过程
  1. 服务器启动并监听指定端口,等待客户端连接。
  2. 客户端启动并尝试连接到服务器。
  3. 服务器接受客户端的连接请求,并创建新线程处理该连接。
  4. 客户端向服务器发送数据,服务器通过 process() 方法处理数据(回显),并将数据发送回客户端。
  5. 客户端接收到服务器的响应并打印出来。
  6. 当客户端输入结束后,关闭连接。服务器在客户端关闭连接后释放资源。

这个简单的TCP回显客户端和服务器示例展示了TCP协议的基本使用,包括连接建立、数据传输和连接关闭。TCP协议的特点是面向连接、保证数据的可靠传输,适用于需要稳定数据传输的应用场景。

5.解释一下这里为什么要用scanner以及为什么要加换行符 \n
1.使用 Scanner 的原因:
  1. 简单性Scanner 是 Java 中一个非常基础且广泛使用的类,用于解析基本类型和字符串的简单文本输入。它提供了方便的方法来获取不同类型的输入,如 nextInt(), nextLine() 等。

  2. 读取文本数据:在 TCP 通信中,通常会传输文本数据。Scanner 能够很好地处理文本数据的读取,尤其是当数据以行的形式发送时。

  3. 按行读取ScannernextLine() 方法可以读取整行的输入,这在处理来自网络的文本消息时非常有用,尤其是当您不知道消息的具体长度时。

2.加入换行符 \n 的原因:
  1. 消息边界:TCP 是一个面向流的协议,这意味着数据在传输时是连续的字节流,没有明确的边界。通过在每条消息的末尾添加一个换行符 \n,您可以在读取端明确地知道一条消息的结束,从而方便地解析消息。

  2. 简化客户端处理:当服务器接收到带有换行符的消息时,ScannernextLine() 方法将会在换行符处停止读取,这使得服务器能够按行读取客户端发送的消息,而不需要额外的逻辑来确定消息的结束。

  3. 协议简单化:使用换行符作为消息边界是一种简单的协议设计,它简化了消息的发送和接收逻辑。当然,这要求发送的消息中不能包含换行符本身,除非进行了适当的转义处理。

  4. 通用性:换行符 \n 是一种通用的文本消息分隔符,在许多网络协议和文本处理场景中广泛使用,因此它易于理解和实现。

3.注意事项:
  • 消息终止符:在使用换行符作为消息边界时,确保发送的消息中不包含换行符,或者在处理时能够正确地识别和处理它。
  • 性能考虑:对于大量数据的传输,使用 Scanner 可能不是最高效的选择,因为它是为简单文本处理设计的。对于二进制数据或大量文本数据的处理,可能需要更高效的 I/O 操作,如使用 BufferedReader 和 BufferedWriter,或者 InputStream 和 OutputStream 的合适缓冲。
  • 安全性:在设计协议时,仅依赖换行符作为消息边界可能不够安全,因为它容易被篡改。在实际应用中,可能需要更健壮的协议来确保数据的完整性和安全性。

以上就是所有对网络编程和套接字的简单介绍了,感谢你的阅读


http://www.ppmy.cn/server/42314.html

相关文章

通过postMessage进行跨域(同源同 IP但是端口不同)、或者跨源(两个页面 IP 不同的网页)直接传值调用

一、 跨域传值 1、语法: 当使用 iframe 跨域传值时,父子页面之间的 postMessage 的语法为: window.parent.postMessage(message, targetOrigin, [transfer]); message 将要发送到目标窗口的数据, 原则上可以是任何类型,但是考虑…

基于Vue图像识别系统毕业设计 ---项目实战(附源码)

前言:Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面&…

Linux 第三十五章

🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…

C++_第十一周做题总结_继承基础

id:68 A圆和圆柱体积算(继承) 题目描述 定义一个CPoint点类,包含数据成员x,y(坐标点)。 以CPoint为基类,派生出一个圆形类CCircle,增加数据成员r(半径)和一个计算圆面积的成员函数…

摸鱼大数据——大数据导论

大数据导论 1、概念 大数据时代: 万物皆数据 ​ 数据概念: 人类的行为及产生的事件的一种记录称之为数据 ​ 数据价值: 对数据的内容进行深入分析,可以更好的帮助了解事和物在现实世界的运行规律 2、大数据诞生 大数据的诞生: 跟随着互联网的发展的,当全球互联…

Windows下配置TortoiseGit 访问Ubuntu虚拟机下Samba共享目录

前言: 本文记录学习使用 Git 版本管理工具的学习笔记,通过阅读参考链接中的博文和实际操作,快速的上手使用 Git 工具。 本文参考了引用链接博文里的内容。 引用: 【TortoiseGit】TortoiseGit安装和配置详细说明-CSDN博客 Git版本管理可视…

【eclipse】如何在IDE里创建一个Java Web项目?

如何在eclipse中创建一个动态Web项目并成功运行? 一、 最终效果 懒得写那么多了…我也不知道该怎么写了,有点乱,有问题可以在评论里留言,我看到会解决的,在这个过程中也踩到了一些坑,但好在有CSDN帮助解决…

NFTScan 升级 Bitcoin NFT 浏览器,全面优化 NFT 数据解析体系

2024 年 5 月 16 号,NFTScan 团队正式全面升级了 Bitcoin NFT 浏览器。随着 Ordinals 铭文生态的崛起开始,Bitcoin 链上活动极大增加,市场被广泛认可,NFT 生态逐渐蓬勃发展。此次 Bitcoin NFTScan 浏览器对 Ordinals 铭文板块进行…

每天一个数据分析题(三百一十三)-漏斗模型

漏斗模型帮助我们理解各不同业务阶段特征,下列哪项不适合用来观测漏斗模型的结果 A. 斜率 B. 粗细 C. 流速 D. 阶段数量 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案

微信公众号自定义分销商城小程序源码系统 带完整的安装代码吧以及系统部署搭建教程

系统概述 微信公众号自定义分销商城小程序源码系统是一款功能强大的电商解决方案,它集成了商品管理、订单处理、支付接口、分销管理等多种功能。该系统支持自定义界面设计,商家可根据自身需求调整商城的页面布局和风格,打造独特的品牌形象。…

Android security知识点总结

Linux sepolicy uses ipk package, each binary has three sepolicy files, they are if (interface), fc (file context), te. opkg install selinux.ipk 1 Chain of Trust 1.1 qcom efuse 对bootloader签名,熔丝文件:sec.dat 1)烧写signed …

LeetCode 3题:无重复字符的最长子串(原创)

【题目描述】 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。示例 2: 输入: s "bbbbb" 输出…

可微分矢量图形光栅化用于编辑和学习

图1. 我们引入了一种通过反向传播将光栅和矢量域联系起来的矢量图形可微分光栅化器。可微分光栅化实现了许多新颖的矢量图形应用。(a)在几何约束下,通过局部优化图像空间度量(如不透明度)来实现交互式编辑。&#xff0…

ClickHouse快速上手

1. 项目目标 (1)了解ClickHouse特性与优势 (2)熟练掌握ClickHouse安装部署 (3)熟练掌握ClickHouse基本用法 2. 项目准备 2.1. 规划节点 主机名 主机IP 节点规划 clickhouse 10.0.1.10 clickhouse…

Redis教程(九):Redis中Hash类型的常用命令

Hash操作&#xff1a; 往Hash中添加两个<key,value>数据&#xff0c;如果没有&#xff0c;自动创建一个Hash结构 hset myhash name dingdada age 23 获取hash中的指定key&#xff0c;获取hash中key是name的值 hget myhash name 获取hash中所有的值&#xff0c;包含k…

【数据结构】第一章 顺序表:顺序表静态分配和动态分配增删改查基本操作的基本介绍及c语言代码实现

文章目录 1.顺序表的定义2.顺序表的实现--静态分配2.1 顺序表的定义2.2 顺序表的初始化2.3 顺序表的插入2.4 顺序表的删除2.5 顺序表的按值查找和按位查找 3.顺序表的实现--动态分配3.1 顺序表的定义3.2 顺序表的初始化3.3 增加动态数组的长度3.4 删除插入按位查找按值查找操作…

【前端系列】什么是yarn

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

鸿蒙HDC命令行工具:模拟操作

模拟操作 uinput用于输入模拟操作&#xff0c;其命令帮助手册为&#xff1a; > hdc shell uinput --help Usage: uinput <option> <command> <arg>... The option are: -M --mouse //模拟鼠标操作 commands for mouse: -m <dx> <d…

看langchain代码之前必备知识之 - python多进程信号接收与处理

文章目录 前言一、示例代码1. 注册信号2.信号处理函数1&#xff09;普通写法2&#xff09;闭包写法 3. 对终止信号的重写1&#xff09;终止前关闭资源2&#xff09;不关闭只抛出异常 二、补充知识点1. signal.SIGTERM 和 signal.SIGINT的区别2. Process(targettask, daemonTrue…

蓝队面试题(二)

应急响应基本思路和流程 收集信息:收集客户信息和中毒主机信息,包括样本 判断类型:判断是否是安全事件,何种安全事件,勒索、挖矿、断网、DoS 等等 抑制范围:隔离使受害⾯不继续扩⼤ 深入分析:日志分析、进程分析、启动项分析、样本分析方便后期溯源 清理处置:杀掉…