Socket 通信机制详解

Socket 是网络编程中一种重要的通信机制,它允许不同的计算机通过网络进行数据交换。

一、 Socket 的概念

Socket(套接字)是计算机网络编程中的一种抽象,它提供了在网络上进行通信的接口。

Socket 本质上是一种通信的端点,它在网络上标识了一个通信链路的两端,并提供了通信双方所需的接口和功能。

通过使用 Socket,可以在不同计算机之间建立连接,并进行数据的传输和交换(网络通信)

二、 Socket 类型

在 Socket 编程中,常见的两种类型是 TCP Socket 和 UDP Socket。

  • TCP Socket:TCP(传输控制协议)是一种面向连接的协议,它提供可靠的、有序的数据传输。TCP Socket 基于 TCP 协议,使用三次握手建立连接,确保数据的可靠性和顺序性。

  • UDP Socket:UDP(用户数据报协议)是一种无连接的协议,它提供了简单的数据传输服务,但不保证数据的可靠性和顺序性。UDP Socket 基于 UDP 协议,无需建立连接,适用于一些实时性要求高、允许一定数据丢失的应用场景。

三、 Socket 的工作原理

3.1 三次握手

这里需要先讲一下TCP 协议中的三次握手。

同步序号:SYN   确认字段:ACK  随机数据:seq

规定:

当SYN=1,ACK=0表示连接请求

当SYN=1,ACK=1表示同意建立连接

如上图,纵向的轴,是一个时间轴。

第一次握手:时间点1,客户端向服务端发送连接请求报文段。ACK=0,SYN=1,seq=x

将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

完成了三次握手,客户端和服务器端就可以开始传送数据。


TCP/IP 三次握手:

TCP/IP 三次握手_tcp三次握手-CSDN博客

创建 Socket与TCP/IP 三次握手有什么关系:

在 TCP 协议中,建立连接通常需要进行三次握手,而创建 Socket 对象通常是在握手之前的准备工作之一用于准备建立连接所需的资源和信息。(创建一个套接字,收集一些计算机的资源,将一些资源绑定套接字里面,以及接受和发送数据的函数等等,这些功能接口在一起构成了socket的编程。)

具体来说,在客户端发起连接之前,通常会创建一个 Socket 对象,然后调用 connect 方法来发起连接请求;

而在服务器端接受连接之前,通常会创建一个 Socket 对象,然后调用 accept 方法来接受连接请求并返回一个新的 Socket 对象,用于与客户端进行通信。

3.2  Socket 的工作原理

当客户端和服务端使用 Socket 进行通信时,它们的工作原理有所不同。

3.2.1 客户端的 Socket 工作原理

  1. 创建 Socket 对象:客户端首先会创建一个 Socket 对象,用于与服务器端建立连接。

  2. 连接服务器:客户端通过调用 Socket 对象的 connect 方法来连接服务器。在连接过程中,客户端会发送连接请求给服务器端。

  3. 发送数据:一旦连接建立成功,客户端就可以通过 Socket 对象的 send 方法向服务器端发送数据。发送的数据通常包括请求信息、参数等。

  4. 接收数据:客户端通过 Socket 对象的 recv 方法来接收服务器端发送的响应数据。客户端会等待服务器端的响应,并在接收到响应后进行相应的处理。

  5. 关闭连接:通信结束后,客户端会调用 Socket 对象的 close 方法来关闭连接,并释放资源。

3.2.2 服务端的 Socket 工作原理

  1. 创建 Socket 对象:服务器端首先会创建一个 Socket 对象,用于监听客户端的连接请求。

  2. 绑定地址和端口:服务器端会将 Socket 对象绑定到一个特定的地址和端口上,以便客户端能够连接到该地址和端口。

  3. 监听连接:服务器端通过调用 Socket 对象的 listen 方法来开始监听客户端的连接请求。一旦调用了 listen 方法,服务器就处于等待客户端连接的状态。

  4. 接受连接:当客户端发起连接请求时,服务器端会调用 accept 方法来接受连接。在接受连接之后,服务器端会创建一个新的 Socket 对象,用于与该客户端进行通信。

  5. 接收和处理数据:一旦连接建立成功,服务器端就可以通过新创建的 Socket 对象来接收客户端发送的数据,并进行相应的处理。服务器端会等待客户端发送数据,并在接收到数据后进行解析和处理。

  6. 发送数据:服务器端也可以通过 Socket 对象的 send 方法向客户端发送数据。这通常发生在服务器端需要向客户端发送响应或其他信息时。

  7. 关闭连接:通信结束后,服务器端会调用 Socket 对象的 close 方法来关闭连接,并释放资源。

总的来说,客户端和服务端的 Socket 工作原理都涉及创建 Socket 对象、建立连接、发送和接收数据以及关闭连接等步骤,但具体的操作和流程略有不同。客户端主要负责发起连接和发送请求,而服务端主要负责监听连接、接受连接和处理请求。

四、代码

4.1 Java代码

4.1.1 客户端代码WebClient

import java.io.*;
import java.net.*;
import java.util.Scanner;public class WebClient {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String messageA; // 储存A发送的消息try {// 创建 Socket,连接到服务器的 IP 地址和端口Socket socket = new Socket("127.0.0.1", 8888);// 获取输入流和输出流InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream();while (true) {  // 一直保持发送System.out.print("输入消息:" + '\t');// 输入消息messageA = scanner.nextLine();// 发送消息给服务器outputStream.write(messageA.getBytes());outputStream.flush(); // 刷新缓冲区,确保消息发送给服务器// 接收服务器的响应byte[] buffer = new byte[1024];int length = inputStream.read(buffer);String response = new String(buffer, 0, length);System.out.println("B: " + response);}// 关闭连接
//            outputStream.close();
//            inputStream.close();
//            socket.close();} catch (IOException e) {System.out.println(e.getMessage());}}
}

4.1.2 客户端代码WebServer

import java.io.*;
import java.net.*;
import java.util.Scanner;public class WebServer {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String messageB = ""; // 储存B发送的消息try {// 创建 ServerSocket,监听指定的端口ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服务启动,等待客户端连接... ");// 等待客户端连接Socket socket = serverSocket.accept();// 获取输入流和输出流InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream();while (true) {// 接收客户端发送的数据byte[] buffer = new byte[1024];int length = inputStream.read(buffer);String message = new String(buffer, 0, length);System.out.println("A: " + message);System.out.print("输入消息:" + '\t');messageB = scanner.nextLine();// 发送响应给客户端outputStream.write(messageB.getBytes());outputStream.flush(); // 刷新缓冲区,确保消息发送给客户端}// 关闭连接
//            outputStream.close();
//            inputStream.close();
//            socket.close();
//            serverSocket.close();} catch (IOException e) {e.printStackTrace();}}
}

4.2 pyhton代码

4.2.1 服务端代码

# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2024 - 04 -10
# @File: server.py
# desc:
import socketdef main():# 创建套接字server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址和端口server_socket.bind(('localhost', 8888))# 监听连接server_socket.listen(1)print("服务启动,等待客户端连接... ")# 接受客户端连接client_socket, client_address = server_socket.accept()print(f"客户端 {client_address} 已连接")while True:try:# 接收客户端消息message = client_socket.recv(1024).decode()print("A:", message)# 发送消息给客户端message_b = input("输入消息:")client_socket.send(message_b.encode())except Exception as e:print("发生异常:", e)break# 关闭连接client_socket.close()server_socket.close()if __name__ == "__main__":main()

4.2.2 客户端代码

# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2024 - 04 -10
# @File: client.py
# desc:
import socketdef main():# 创建套接字client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 连接服务器client_socket.connect(('localhost', 8888))while True:try:# 发送消息给服务器message_a = input("输入消息:")client_socket.send(message_a.encode())# 接收服务器响应response = client_socket.recv(1024).decode()print("B:", response)except Exception as e:print("发生异常:", e)break# 关闭连接client_socket.close()if __name__ == "__main__":main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/807047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 ts环境下的PropType

简介 在Typscript中,我们可以使用PropType进行类型的推断与验证。在日常的开发中我们常常会遇到下面这样的场景: 我们通过request请求从服务端获取了一条数据,数据是个Array的格式,Array中的每个元素又是一个对象,像下…

坚持十天做完Python入门编程100题第三天加班

坚持十天做完Python入门编程100题第三天加班 第24题 扫描文件列表第25题 如何将字典转换成JSON并写入json文件?第26题 JSON转换成字典 第24题 扫描文件列表 如何扫描当前目录下的文件列表?解析:可以使用python内置的glob模块,用法…

Golang | Leetcode Golang题解之第21题合并两个有序链表

题目&#xff1a; 题解&#xff1a; func mergeTwoLists(list1, list2 *ListNode) *ListNode {if list1 nil {return list2 // 注&#xff1a;如果都为空则返回空}if list2 nil {return list1}if list1.Val < list2.Val {list1.Next mergeTwoLists(list1.Next, list2)re…

项目管理工具——使用甘特图制定项目计划的详细步骤

甘特图是一种直观的项目管理工具&#xff0c;它有助于我们清晰地展示任务安排、时间管理和项目的进度。以下是使用甘特图制定项目计划的详细步骤&#xff1a; 1、创建项目&#xff1a;首先&#xff0c;在进度猫中创建新的项目&#xff0c;并设置项目的时间、工作日等参数。根据…

44-技术演进(下):软件架构和应用生命周期技术演进之路

应用、系统资源、应用生命周期管理这 3 个维度&#xff0c;构成了我们对云的所有诉求。 我会介绍下应用维度和应用生命周期管理维度的技术演进。 我们就先来看下软件架构的演进之路。 软件架构的演进 软件架构技术演进如下图所示&#xff1a; 单体架构 在单体架构中&#xff…

乐得瑞LDR6020 Type-C 一拖二/一拖三快充线方案介绍

随着移动设备的普及和功能的日益增强&#xff0c;电池续航成为了用户关注的重点之一。为了满足用户对于快速充电的需求&#xff0c;各大厂商纷纷推出了各种快充技术和产品。在这个背景下&#xff0c;乐得瑞公司推出了一款名为LDR6020的一分二PD快充线方案&#xff0c;该方案采用…

Unity 九宫格

1. 把图片拖拽进资源文件夹 2.选中图片&#xff0c;然后设置图片 3.设置九宫格 4.使用图片&#xff0c;在界面上创建2个相同的Image,然后使用图片&#xff0c;修改Image Type 为Sliced

Nodejs 第六十二章(短链接)

短链接介绍 短链接是一种缩短长网址的方法&#xff0c;将原始的长网址转换为更短的形式。它通常由一系列的字母、数字和特殊字符组成&#xff0c;比起原始的长网址&#xff0c;短链接更加简洁、易于记忆和分享。 短链接的主要用途之一是在社交媒体平台进行链接分享。由于这些…

配置及第三方授权申请教程

项目需要配置的地方不多&#xff0c;主要就两个地方需要注意&#xff1a;邮箱授权和第三方授权需要提前申请 1.基本设置 1.1 打开application.yml&#xff0c;修改数据库ip等基本信息 这些基本的配置就不多说了&#xff0c;基本就是改下服务器ip和账号密码什么的 1.2 获取QQ…

RX4901CE自带SPI接口,适合用在需高精度和快速响应的设备

传统的模拟温度补偿晶振采用热敏电阻等元器件来检测环境温度&#xff0c;将温度信息做相应变换后控制晶振的输出频率用来实现稳定输出&#xff0c;但是这种做法频率补偿精度有限。伴随目前电路计算频率越来越高&#xff0c;更多工业级的高时间精度和快速时间响应的应用出现&…

MLeaksFinder报错

1.报错&#xff1a;FBClassStrongLayout.mm 文件&#xff1a;layoutCache[currentClass] ivars; 解决&#xff1a;替换为layoutCache[(id)currentClass] ivars; 2.编译正常但运行时出现crash indirect_symbol_bindings[i] cur->rebinding FBRetainCycleDetector iOS15 …

Mybatis分页查询用PageHelper插件

首先看接口文档需求 看响应数据样例&#xff0c;那么咱们先自定义一个bean来满足这个需求&#xff0c;这里定义PageBean实体类 package com.itheima.pojo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.List;//分…

Ubuntu-22.04安装Virtualbox并安装Windows10

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Virtualbox是什么&#xff1f;二、安装Virtualbox1.关闭Secure Boot2.安装 三、安装Windows101.新装虚拟机基本配置2.新装虚拟机核心配置 总结 前言 虚拟机…

Harmony鸿蒙南向驱动开发-UART

UART指异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;&#xff0c;是通用串行数据总线&#xff0c;用于异步通信。该总线双向通信&#xff0c;可以实现全双工传输。 两个UART设备的连接示意图如下&#xff0c;UART与其他模块一般用2线&a…

记录一个Kafka客户端Offset Explore连不上的问题

CSDN上的其他人不知道咋想的&#xff0c;这么简单一个问题都要写个收费的回答。那我来写个不收费的&#xff0c; 我昨天把集群重装了一下&#xff0c;再连这个工具就连不上了&#xff08;你先把zk和kafka在集群启起来&#xff09;&#xff0c;报错截图如下&#xff1a; 英文翻…

中位数和众数-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第49讲。 中位数和众数&…

深入浅出Redis(十二):Redis的排序命令Sort

引言 Redis是一款快速、优秀的键值对数据库&#xff0c;提供丰富的数据结构能在各种场景下实现功能&#xff0c;同时也提供丰富的命令来完成各种各样的功能&#xff0c;本篇文章将深入浅出的解析Sort命令的原理以及使用 原理 Sort 命令用来对list、set、zset对象进行排序&am…

JavaEE实验三:3.5学生信息查询系统(动态Sql)

题目要求: 使用动态SQL进行条件查询、更新以及复杂查询操作。本实验要求利用本章所学知识完成一个学生信息系统&#xff0c;该系统要求实现3个以下功能: 1、多条件查询&#xff1a; 当用户输入的学生姓名不为空&#xff0c;则根据学生姓名进行学生信息的查询&#xff1b; 当用户…

Day:006(1) | Python爬虫:高效数据抓取的编程技术(爬虫工具)

selenium介绍与安装 Selenium是一个Web的自动化测试工具&#xff0c;最初是为网站自动化测试而开发的&#xff0c;类型像我们玩游戏用的按键精灵&#xff0c;可以按指定的命令自动操作&#xff0c;不同是Selenium 可以直接运行在浏览器上&#xff0c;它支持所有主流的浏览器&am…

C++11 设计模式1. 模板方法(Template Method)模式学习。UML图

一 什么是 "模板方法&#xff08;Template Method&#xff09;模式" 在固定步骤确定的情况下&#xff0c;通过多态机制在多个子类中对每个步骤的细节进行差异化实现&#xff0c;这就是模板方法模式能够达到的效果。 模板方法模式属于&#xff1a;行为型模式。 二 &…