当前位置:网站首页>【网络篇】套接字编程
【网络篇】套接字编程
2022-06-11 03:41:00 【Suk-god】
1、前提知识铺垫
1.1 认识端口—port
本质:端口号是一个2字节16位的无符号整数,范围是[0,65535]
作用:端口号是用来标识一个进程,告诉操作系统,当前的数据要交给那一个进程来处理
注意事项:一个端口只能被一个进程占用
一个进程可以占用多个端口一些知名端口:
[0,1023] 范围内的端口已经被一些知名的协议所使用,我们在编写代码的时候不要使用该范围内的数据作为端口号
MySQL----3306端口
Oracle----1521端口
1.2 网络数据的五元组信息
{源IP、 目的IP 、源端口、目的端口、 协议}
| 名称 | 作用 |
|---|---|
| 源IP | 标识网络数据是从哪台主机发出的 |
| 目的IP | 标识数据要去往哪一台主机 |
| 源端口 | 标识网络数据是从“源IP”对应的这台主机的哪个进程产生的 |
| 目的端口 | 通过目的IP找到目的主机之后,需要利用目的端口找到对应的进程 |
| 协议 | 标定双方传输数据时使用的协议,一般是UDP/TCP |
1.3 网络字节序
字节序又称为端序或者尾序。指的是多字节数据在内存中存放的顺序。
我们接触的字节序分为两类:小端字节序和大端字节序
他们是两种数据在内存中存放顺序的不同规则
| 字节序 | 特点 |
|---|---|
| 小端字节序 | 数据的低权值位对应空间的低地址 |
| 大端字节序 | 数据的低权值位对应空间的高地址 |
如何判断自己的机器遵守的是哪一种存储规则?
方式一:指针+变量+强制类型转换验证
方式二:利用联合体的存储特性来判断
有了上面的铺垫,我们来认识一下主机字节序与网络字节序
主机字节序:指的是机器本身的字节序,如果是大端,则主机字节序为大端,如果是小端,则主机字节序为小端
网络字节序:规定网络传输数据的时候采用大端字节序进行传输
1.4 主机字节序与网络字节序的相互转换
既然网络字节序是大端字节序,现在假设有AB两台主机,他们之间需要通过网络进行通信,我们分析A向B发送消息这一单程。
A向B发送的数据,通过网络传输时一定要转换为网络字节序,否则传输的数据可能会出错(这取决于主机A是大端还是小端机器)
B从网络中接收A发送的数据时,也需要将数据从网络字节序转换为B主机的主机字节序
这个具体的转换过程并不需要我们自己实现,OS为我们提供了转换的接口

1.5 TCP协议与UDP协议的特性和区别
UDP:
TCP
2、UDP_socket编程
2.1 编程流程
服务端
Ⅰ、创建套接字
Ⅱ、绑定地址信息
Ⅲ、收发消息
Ⅳ、使用完毕后关闭套接字客户端
Ⅰ、创建套接字
Ⅱ、不推荐绑定地址信息
不推荐在代码手动绑定地址信息
Ⅲ、收发消息
Ⅳ、使用完毕后关闭套接字
图示:
总结:
1、为什么要创建套接字?
将进程和网卡进行绑定,进程可以从网卡中接收消息,也可以通过网卡发送消息。
2、绑定地址信息具体干了什么?
绑定IP和端口。目的是为了在网络中表示一台主机和一个进程。这样一来,对于接收方而言,发送数据的人就知道接受方的在哪台机器的哪个进程了;对于发送方而言,能够标识网络数据是从哪台机器的哪个进程发送出去的。
2.2 编程接口
2.2.1 创建套接字
#include<sys/socket.h>
int socket(int domain, int type, int protocol)
参数:
返回值:
2.2.2 绑定接口
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
参数:
sockfd-----创建套接字时返回的套接字描述符
addr-----绑定的地址信息(IP + port)
addrlen----绑定的地址信息的长度
注意:这里的 struct sockaddr是一个通用的数据结构!结构如下:
我们在组织参数的时候,传递的并不是上面的这个通用数据结构,而是struct sockaddr_in这个结构体变量,具体内容如下:
2.2.3 发送接口
ssize_t sendto(int sockfd, const void* buf, size_t len, int flags,const struct sockaddr* dest_addr, socklen_t addrlen);
参数:
返回值:
2.2.4 接收接口
ssize_t recvfrom (int sockfd, void* buf, size_t len, int flags,struct sockaddr* src_addr, socklen_t* addrlen);
参数:
2.2.5 关闭接口
int close(int fd)
2.3 编程代码

具体代码---->点这里
3、TCP_socket编程
3.1 编程流程
服务端
创建套接字
绑定地址信息
监听
获取新连接
收发数据
关闭连接客户端
创建套接字
不推荐绑定地址信息
发起连接
收发数据
关闭连接
图示:
总结:
监听的含义
监听TCP客户端新的连接,同客户端建立TCP连接。(此时,TCP的建立在内核中就完成了)
获取新连接的含义
获取新连接的套接字描述符,每一个TCP连接会产生一个新的套接字描述符
发起连接的含义
向服务端发起连接
3.2 编程接口(较UDP编程新增的接口)
3.2.1 监听接口
int listen(int sockfd, int backlog)
参数
返回值
成功—>0
失败—>-1
3.2.2 获取新连接
int accept(int sockfd, struct sockaddr* addr, socklen_t * addrlen);

关于获取新连接这一接口的理解:
3.2.3 发起连接
int connect (int sockfd, const struct sockaddr* addr, socklen_t addrlen)


3.2.4 收发数据
接收数据:
ssize_t recv(int sockfd, void* buf, size_t len, int flags);

注意:返回值为0表示对端关闭连接了,如果此时的对端指的是客户端,则服务端需要将对应的新套接字描述符关闭!
发送数据
ssize_t send(int sockfd, const void* buf, size_t len, int flags)

注意:
服务端在发送数据的时候,第一个参数sockfd传递的是新创建的套接字描述符,并不是侦听套接字的套接字描述符
3.3 编程代码
期望完成的功能:服务端和多个客户端之间能够正常的通信!
3.3.1 TCP_demo
服务端主要代码:
客户端主要代码 :
运行结果分析:
分析出现这种情况的原因:
首先,第二个客户端的代码能够执行到提示输入语句处,说明此时该客户端与服务端已经建立了连接。并且客户端发送数据后没有报错,说明客户端数据发送是成功的。因此问题肯定是出在服务端的代码。
我们可以通过命令netstat来查看当前网络连接状态以及相关信息。
综上所述,我们单线程的TCP代码就目前而言,只能服务于单个客户端的情况。(注意:后续可以通过多路转接IO模型实现服务器与客户端是一对多的现象)
基于这种情况,我们需要找到一种方法,能够同时让多个客户端都享受服务。
因此,我们可以让服务端的一个进程(线程)只负责与客户端建立连接,剩下的一批进程(线程)可以各自与一个客户端进行沟通。这样就可以达到我们的目标了。因此TCP结合多进程/多线程就脱颖而出~
下面分别介绍TCP 与多进程和多线程结合的代码
3.3.2 TCP + 多进程
首先,对于客户端的代码而言,不需要做出任何的改动!因为客户端只需要一直和服务端进行通信即可!
主要的更改是在服务端,我们通过创建子进程的方式来实现职责的分离,也就是父进程只负责与客户端建立连接,而子进程负责与客户端进行收发消息。
具体核心代码如下:
注意几点细节:
1、子进程是拷贝父进程的PCB,因此需要父进程先与客户端建立连接,也即在父进程的PCB中的fd_array中有了该套接字的文件描述符之后再创建子进程
2、子进程创建成功过,由于它只需要和客户端进行收发消息,因此只需要accept返回的新套接字描述符即可,所以需要将拷贝自父进程的侦听套接字关闭
3、客户端如果将连接关闭,则子进程需要将对应的套接字即文件描述符关闭,然后该进程需要退出。
但是注意:退出时,一定要通知父进程来回收子进程的退出状态信息,否则子进程就会编程僵尸进程!但是我们不能采用wait || waitpid来回收。因为wait具有阻塞属性,而waitpid需要搭配循环来使用,均不符合我们的预期。我们可以通过信号量的方式来处理,即改写SIGCHLD信号!
具体代码参考 TCP_process服务端
3.3.3 TCP + 多线程


具体代码参考—TCP_thread服务端代码
以上就是关于socket编程的相关总结~感觉有所帮助的友友们欢迎评论转发!!
边栏推荐
- pmm监控oracle
- Shell script binary encryption
- 【CNN】|How much position information do convolutional neural networks encode?
- Application of NTP network time server (PTP clock synchronization) in it network
- After the college entrance examination, what can I do and how should I choose my major-- From the heart of a college student
- OpenGL第十一章 多光源
- 如何做编程知识投资及减少知识失效的影响
- 软件工程笔记之期末复习(简答)
- Manual testing cannot be changed to automated testing. What is missing?
- 如何提高回归测试效率
猜你喜欢
![From function test to advanced automation test, I stayed up 7 days to sort out this 3000 word super complete learning guide [with network disk resources]](/img/bd/478558d50aa14320c70d3f8a7b76a5.png)
From function test to advanced automation test, I stayed up 7 days to sort out this 3000 word super complete learning guide [with network disk resources]

Pthread in the multithreaded Trilogy

Docker swarm installing MySQL Cluster

基于SSM框架的学生在线教育教学课程管理系统

JMeter piezometric interface programming North

Quartz:老而弥坚的开源任务调度框架,用起来够丝滑

Student online education and teaching course management system based on SSM framework

Why is vfly, a high-end brand of Yadi that does not live up to its name, not high-end?

The key data of music genuine rate is missing. What is the odds of Netease cloud music IPO?

Docker uses PXC to build a MySQL Cluster (mysql:5.7.24)
随机推荐
Le tri le plus couramment utilisé de JS - - série JS déchiquetée à la main
Comparison of four delivery modes of Message Oriented Middleware
pmm监控oracle
Build local source 2.0 for Galaxy Kirin server version
人与人的一些不同
How PTP helps several major operators meet 5g timing requirements
Lua removing elements from a loop in a list
WPF of open source project hero alliance
OpenSSL enc encryption and decryption
【CNN】|How much position information do convolutional neural networks encode?
Web upload file Preview
右键 powershell here 功能添加
[cnn]|differences between CNN and transformer
Quartz:老而弥坚的开源任务调度框架,用起来够丝滑
A - Eddy‘s AC难题(C语言)
NTP time server (GPS Beidou satellite synchronous clock) application boiler monitoring system
Notes on redisson distributed lock usage
Quartz: an old and robust open source task scheduling framework, which is smooth enough to use
OpenGL第八章 材质material
Pci/pcie related knowledge