Socket编程(UDP和TCP)学习(自顶向下计网)
迪丽瓦拉
2025-05-30 07:40:43
0

socket编程

socket:套接字是作为端点在服务器端和客户端程序之间建立双向网络通信链路的软件对象。在 UNIX 中,套接字也可以被称为操作系统(OS)中进程间通信(IPC)的端点。可以把进程比作房子,而socket就是房门。应用相当于房子内的一侧,而传输层协议相当于房门外的一侧。

 

包括两种传输层服务的socket类型:

 

  • TCP:可靠的、字节流的服务、面向连接(connection-oriented)

  • UDP:不可靠(对数据的递送无保证)服务、无连接、发送独立的数据报

什么是可靠?

传过去是什么,那边收到的就是什么,原原本本,不丢失

字节流:

  • A reliable byte stream is a common service paradigm in computer networking; it refers to a byte stream in which the bytes which emerge from the communication channel at the recipient are exactly the same, and in exactly the same order, as they were when the sender inserted them into the channel.

面向连接:

  • A connection between client and server is established before data can be sent

  • The server must be listening (passive open) for connection requests from clients before a connection is established.

  • Three-way handshake (active open), retransmission, and error detection adds to reliability but lengthens latency.

编写一个网络应用

一个典型的网络应用包括一个客户端程序和一个服务端程序,对应两个不同的端点系统。当执行这两个程序时,客户端进程和服务端进程生成了,这两个进程会通过向socket读写来进行交流。

有两种网络应用。一种是遵循协议标准的,例如RFC或者其他标准文档。

RFC:Request For Comments.它是一个描述 Internet 和 TCP/IP 的标准、协议和技术的文档。自1969年以来,已经发布了大约2400个关于各种网络协议、程序、应用程序和概念的评论请求(RFC)

另一种是专有的网络应用,客户端和服务端程序遵循的并不是开源的RFC或者其他文档。这种情况下开发者需要同时写客户端和服务端的程序,并且由于协议不开源,其他开发者不能够参与开发。

UDP套接字编程

使用UDP时,在发送进程(sending process)可以通过socket发出数据报之前,必须要给数据报附上这段数据的目的地的地址。 在数据报通过发送方的socket之后,Internet会根据地址路由到接收进程(receiving process)。 当数据报到达接收方的socket时,接收进程将通过socket检索数据报,然后检查数据报的内容并采取适当的行动。

那么附着在数据报中的地址包含了哪些内容呢?你可能会想到IP地址会是目的地地址的一部分,通过在数据报中包含IP地址,Internet中的路由器就可以将数据报发送到目的地主机(host)。但是一个host可能运行着许多的网络应用进程,每一个进程都带有一个或者多个socket,因此需要对特定的socket进行区分。当一个socket被创建时,就会有一个对应的端口号(port number)分配给这个socket。所以在目的地地址中还包含了socket的端口号。

总而言之,发送进程向数据包附加一个目的地址,该目的地址由目的地主机的 IP 地址和目的地套接字的端口号组成。此外,正如我们即将看到的,发送方的源地址ーー包括源主机的 IP 地址和源套接字的端口号ーー也附加到数据包中。但是,将源地址附加到数据包通常不是由 UDP 应用程序代码完成的; 相反,它是由底层操作系统自动完成的。

为什么还要附带源主机的地址和端口号?

让目的地主机能够把回答(response)发送回发送方。

接下来根据以下的cs应用来进行UDP和TCP的socket编程。

  1. 客户端从键盘读取一行字符(数据)并将数据发送到服务器。

  1. 服务器接收数据并将字符转换为大写。

  2. 服务器将修改后的数据发送给客户端。

  3. 客户端接收修改后的数据,并在其屏幕上显示该行

让我们从UDP开始吧。

UDPClient.py

from socket import * 
​
serverName = '127.0.0.1' 
serverPort = 12000 
clientSocket = socket(AF_INET, SOCK_DGRAM) 
message = input('Input lowercase sentence:') 
​
clientSocket.sendto(str.encode(message), (serverName, serverPort)) 
modifiedMessage, serverAddress = clientSocket.recvfrom(2048) 
print(modifiedMessage) 
clientSocket.close()
  1. from socket import *: This line imports the socket module, which provides low-level network functionality.

  2. serverName = '127.0.0.1': This line sets the IP address of the server that the client will send datagrams to.

  3. serverPort = 12000: This line sets the port number that the server is listening on.

  4. clientSocket = socket(AF_INET, SOCK_DGRAM): This line creates a new socket object called clientSocket that uses the IPv4 address family and the datagram-oriented protocol type.

  5. message = input('Input lowercase sentence:'): This line prompts the user to enter a message to send to the server.

  6. clientSocket.sendto(str.encode(message), (serverName, serverPort)): This line sends the message to the server at the specified IP address and port number.

  7. modifiedMessage, serverAddress = clientSocket.recvfrom(2048): This line waits for a response from the server and stores the response in the modifiedMessage variable. The serverAddress variable stores the IP address and port number of the server that sent the response.

  8. print(modifiedMessage): This line prints the response from the server to the console.

  9. clientSocket.close(): This line closes the socket object.

UDPServer.py

from socket import *
serverPort = 12000 
serverSocket = socket(AF_INET, SOCK_DGRAM) serverSocket.bind(('127.0.0.1', serverPort)) 
print("The server is ready to receive") 
while 1:message, clientAddress = serverSocket.recvfrom(2048)     modifiedMessage = message.upper()                          serverSocket.sendto(modifiedMessage, clientAddress) 
  1. from socket import *: This line imports the socket module, which provides low-level network functionality.

  2. serverPort = 12000: This line sets the port number that the server will use to listen for incoming datagrams.

  3. serverSocket = socket(AF_INET, SOCK_DGRAM): This line creates a new socket object called serverSocket that uses the IPv4 address family and the datagram-oriented protocol type.

  4. serverSocket.bind(('127.0.0.1', serverPort)): This line binds the serverSocket object to the server’s IP address and the specified port number.

  5. print("The server is ready to receive"): This line prints a message to the console indicating that the server is ready to receive datagrams.

  6. while 1:: This line starts an infinite loop that listens for incoming datagrams and sends a response back to the client.

  7. message, clientAddress = serverSocket.recvfrom(2048): This line waits for an incoming datagram and stores the message in the message variable. The clientAddress variable stores the IP address and port number of the client that sent the datagram.

  8. modifiedMessage = message.upper(): This line converts the received message to uppercase and stores it in the modifiedMessage variable.

  9. serverSocket.sendto(modifiedMessage, clientAddress): This line sends the modified message back to the client at the IP address and port number stored in the clientAddress variable.

编译并运行UDPClient.py和UDPServer.py,在UDPClient中输入要转化为大写的句子,这个字符串经过编码,以字节流的形式通过socket发送给UDPServer,在UDPServer中消息变成大写,返回给UDPClient。

TCP套接字编程

与 UDP 不同,TCP 是一种面向连接的协议。这意味着在客户机和服务器开始相互发送数据之前,它们首先需要握手并建立 TCP 连接。TCP 连接的一端连接到客户端套接字,另一端连接到服务器套接字。在创建 TCP 连接时,我们将客户端套接字地址(IP 地址和端口号)和服务器套接字地址(IP 地址和端口号)与其关联。建立了 TCP 连接之后,当一方想要向另一方发送数据时,它只需通过套接字将数据发送到 TCP 连接。这不同于 UDP,对于 UDP,服务器必须在将数据包放入套接字之前将目的地址附加到数据包。

现在让我们更仔细地研究一下 TCP 中客户机和服务器程序的交互。客户端负责启动与服务器的联系。为了让服务器能够对客户端的初始联系人做出反应,服务器必须做好准备。 这意味着两件事。首先,与 UDP 的情况一样,TCP 服务器必须作为进程运行,然后客户机才会尝试发起联系。其次,服务器程序必须有一个特殊的门ーー更确切地说,是一个特殊的套接字ーー来自运行在任意主机上的客户机进程的初始联系。使用我们的房子/门类比进程/插座,我们有时将客户的初始接触称为“敲响欢迎的门”。

随着服务器进程的运行,客户端进程可以启动到服务器的 TCP 连接。这是通过在客户端程序中创建一个 TCP 套接字来完成的。当客户端创建其 TCP 套接字时,它指定了服务器端欢迎套接字(welcoming socket)的地址,即服务器主机的 IP 地址和套接字的端口号。创建套接字后,客户机发起三次握手并与服务器建立 TCP 连接。发生在传输层内的三次握手对于客户端和服务器程序来说是完全不可见的。

在三方握手过程中,客户端进程敲响了服务器进程的欢迎门。当服务器“听到”敲门声时,它就会创建一个新的门ーー更确切地说,是一个专门为该特定客户端设置的新socket。在下面的示例中,欢迎门(welcoming door)是一个 TCP 套接字对象,我们称之为 serverSocket; 新创建的用于建立连接的客户端套接字称为 connec-tionSocket。第一次接触到 TCP 插座的学生有时会混淆欢迎套接字(welcoming socket)(这是所有想要与服务器通信的客户端的初始联系点) ,以及每个新创建的服务器端连接套接字(connection socket)(后来为与每个客户端通信而创建)。

 

 

从应用程序的角度来看,客户端的套接字和服务器的连接套接字通过管道直接连接。如图所示,客户端进程可以向其套接字中发送任意字节,TCP 保证服务器进程将接收(通过连接套接字)发送的顺序中的每个字节。因此,TCP 在客户端和服务器进程之间提供了可靠的服务。此外,正如人们可以进出同一扇门一样,客户端进程不仅仅发送字节,还会从它的socket接收字节;相似的,服务端进程也不仅仅发送字节,还会从它的connection socket接收字节。

 

TCPClient.py

from socket import *
​
serverName = '127.0.0.1'
serverPort = 13000
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
sentence = input('Input lowercase sentence:')
clientSocket.send(str.encode(sentence))
modifiedSentence = clientSocket.recv(1024)
print('From Server:', modifiedSentence)
clientSocket.close()

TCPServer.py

from socket import *
​
serverPort = 13000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('127.0.0.1', serverPort))
serverSocket.listen(1)
print('The server is ready to receive')
while 1:connectionSocket, addr = serverSocket.accept()sentence = connectionSocket.recv(1024)capitalizedSentence = sentence.upper()connectionSocket.send(capitalizedSentence)connectionSocket.close()

回顾一下什么是协议。协议是两个或更多个实体之间交换信息的格式和顺序,以及在发送和/或接收信息或其他事件时所采取的行动。协议是计算机网络的核心概念,TCP和UDP也是协议,经过socket编程的学习,我对协议有了更多直观的感觉。

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...