网络套接字

打印 上一主题 下一主题

主题 1743|帖子 1743|积分 5229

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
预备知识

源IP地址和目的IP地址
因特网上每台主机都有唯一的IP地址,源IP地址就是计算机发送消息起始的地址,目的IP地址就是对端计算机的地址
源MAC地址和目的MAC地址
这两个地址是数据链路层的在局域网中起作用的,但是这两个地址在数据进入另一个局域网之后就会变化,源MAC地址表示上一个地址,目的MAC地址表示下一个地址
上述IP地址和MAC地址就可以理解为公交车站台,源IP地址就是起始站台,目的IP地址就是终点站台,源MAC地址就是上一个站台,目的MAC地址就是下一个站台。以是源IP地址和目的IP地址稳定,源MAC地址和目的MAC地址会改变
端口号
标识唯一的进程 ,为什么进程ID(pid)已经可以标识唯一进程了,为什么还需要端口号?
进程ID是属于体系层面唯一标识,但是端口号是网络中的概念,没必要让两个方面的概念用相同的方式来举行标识
底层上实在是创建了端口号和PID的哈希映射
源端口号和目的端口号
socket通信实质上就是两个进程之间的通信,以是源端口号就是“发送端的端口号”,目的端口号就是“接收端的端口号”
TCP和UDP协议
传输层
TCP:有毗连,可靠的,字节流
UDP;无毗连,不可靠的,数据包
网路字节序
磁盘文件存储数据有大小端之分,在网络中数据也有大小端之分
TCP/IP协议接纳大端字节
以是如果主机是接纳小端,即低地址低字节,就需要使用主机转网络,把数据转为大端
  1. #include <arpa/inet.h>
  2. uint32_t htonl(uint32_t hostlong);
  3. uint16_t htons(uint16_t hostshort);
  4. uint32_t ntohl(uint32_t netlong);
  5. uint16_t ntohs(uint16_t netshort);
复制代码
函数名当中的h表示host,n表示network,l表示32位长整数,s表示16位短整数


socket编程

socket常用API

创建套接字,TCP/UDP 客户端+服务器端

domain:协议家属 
type:TCP/UDP分别填入参数SOCK_STREAM或SOCK_DGRAM
protocol:0,使用默认,通过前两个参数举行推导
返回值:返回套接字文件形貌符,失败返回-1

绑定端口号,TCP/UDP 客户端+服务器端

绑定套接字和IP地址、端口号
sockfd:socket返回值
addr:强转sockaddr_in
addrlen:addr布局的长度
返回值:乐成返回0,失败返回-1
这里绑定IP地址一样平常使用INADDR_ANY,任意客户端毗连都可以毗连

监听套接字,TCP 服务器

把套接字从发起毗连的客户端,变成接收毗连的服务端,进入LISTEN状态
backlog:表示未毗连队列和毗连队列之和的最大数目,当再次来毗连时,超出这个值,就会直接拒绝请求
返回值:乐成返回0,失败返回-1

接收请求 TCP 服务器
这里参数部门_Nullable restrict关键字分别表示addr可以为NULL和表明唯一

addr:客户端地址和端口号,调用之后自动添补
addrlen:addr布局长度,调用之前设置为sizeof(struct sockaddr),调用之后返回实际长度
注意:
返回值:返回一个新的文件形貌符,这个形貌符是用于服务端和客户端之间通信的。
肯定要和前面的监听文件形貌符做区别

创建毗连 TCP 客户端 

addr:服务端的IP地址和端口号
addrlen:addr布局的长度
返回值:乐成返回0,失败返回-1


sockaddr布局


套接字不但支持网络之间通信,还支持本地通信,以是sockaddr_in是网络通信的布局,需要端口号和IP地址;socketaddr_un是本地通信
为了本地通信和网络通信都能使用同一套套接字,以是有了sockaddr布局
为什么不使用void*来更换sockaddr*?
void*的前十六位就能够区别是本地还是网络,但是当时C语言还没有void*,而sockaddr*是在体系层面的接口,不能轻易修改体系底层的代码。
为什么会有这么多本地进程间通信的办法?
早期许多实行室都在研究通信的办法,以是就出现了管道、消息队列、共享内存、信号量等本地进程通信的方式

接口函数都是sockaddr,以是需要把sockaddr_in举行强转才华够传参


sockaddr_in布局
sin_family:协议家属,AF_UNIX表示本地通信,AF_INET(IPv4)或者AF_INET6(IPv6)表示网络通信
sin_port:端口号
sin_addr:IP地址,类型是struct in_addr



 地址转换函数

通常使用点分十进制来表示IP地址,但是sockaddr_in中成员sin_addr表示IP地址,以是需要字符串的IP地址和网络字节序的IP地址之间相互转换
  1. // 将点分十进制字符串表示的IPv4地址转换为网络字节序
  2. int inet_aton(const char *cp, struct in_addr *inp);
  3. //返回值就是转换的网络字节序
  4. in_addr_t inet_addr(const char *cp);
  5. //将网络字节序的IPv4地址转换为点分十进制字符串
  6. char *inet_ntoa(struct in_addr in);
  7. //这些函数是 inet_aton 和 inet_ntoa 的更通用版本,支持IPv4和IPv6地址
  8. int inet_pton(int af, const char *src, void *dst);
  9. const char *inet_ntop(int af, const void *src, char *dst, size_t size);
复制代码

UDP服务端和客户端简单实现

MyUdpserver · user_11620652/linux - 码云 - 开源中国
因为UDP没有创建毗连,以是使用recvfrom来接收数据,sendto来发送数据
recvfrom


sockfd:文件形貌符,在该文件形貌符索引的文件读取数据
buf:读取的数据存放位置
len:读取数据长度,这里读取数据长度-1,是把读取的数据看作是一个字符串,末了是'\0'
flags:一样平常设置为0,表示堵塞读
src_addr:对端的网络相干属性布局,函数接收到数据时,自动添补对端网络信息
addrlen:对端src_addr布局大小 ,调用之前设置src_addr布局体大小,调用后返回实际写入的大小


sendto


参数部门与recvfrom类似,但是sendto是要发送数据,以是就需要直到对端IP地址和port的信息 ,用户自己添补到dest_addr

客户端的绑定

为什么客户端可以不用绑定端口号?
服务端绑定端口号是因为服务端要提供服务,需要唯一的明白的端口号来告诉客户端,让客户端来举行访问,服务端的端口号不能轻易改动,客户端就不需要绑定端口号,操作体系会给当前客户端指定一个唯一的接口
服务端必须绑定唯一的端口号,客户端的端口号可以变化

INADDR_ANY

服务端绑定IP地址时,使用INADDR_ANY表示接收任意地址数据,当只要传入指定服务端的端口号,就可以直接发送给服务端
这是保举的做法,因为一个服务器大概会有多张网卡,也就是说有多个IP地址,以是使用接收任何地址数据,就可以接收到任何发个服务器的请求
这里IP地址设置为0.0.0.0效果也是一样的

TCP实现从服务器翻译

MyTcpServer · user_11620652/linux - 码云 - 开源中国
这里的实现使用了线程池,因为服务器在频仍的接收毗连和销毁毗连,注定会有线程许多线程产生和销毁,以是线程池可以减少这些开销
服务端

服务端实现套接字创建毗连,其他的和UDP实现基本是相同的,如下细节问题需要注意
1、守护进程
让服务端可以在后端实行,关闭当前会话不会影响服务端
2、单例模式创建线程池
这里线程池处理使命,通过队列的方式来处理使命,因为这里设计多线程的操作,以是需要注意线程之间安全和同步问题
3、Task t(sock,clientport,clientip);
这里是初始化使命,方便下一步交给线程池处理
4、ThreadPool<Task>::GetInstance()->ush(t);
这里插入线程池处理,线程池里使用了同步机制,以是当使命队列没有使命时就会等待,当插入使命时就会唤醒。



上面的操作就可以开始使命了,翻译也就是在txt文件中英文和中文逐一对应,以是只需要读文件以key-value的情势插入hash容器中,这样当客户端输入一个英文,服务端就可以返回相应的中文

客户端

因为TCP需要创建毗连,以是客户端需要使用connect与服务端创建毗连,上述常用API报告了相应的用法,其他和UDP类似

注意:
上面只是报告了服务端实现的大概过程,具体实现在gitee毗连中,因为那些细节不是TCP的部门,以是就不加赘述。



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

半亩花草

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表