如果有多个客户端与服务器发生请求,有两种处理方式,一是顺序处理,二是并发处理(多线程)
字节序转换
数据在计算机中存储时是小端序,但通常情况下网络字节序采用的是大端序,所以需要字节序转换
(PS:之所以采用大端序是因为早期的网络协议使用的就是大端序,后续为了统一就沿用大端序了)
uint16_t htons(uint16_t hostshort);//短整型 主机->网络
uint32_t htonl(uint32_t hostlong);//整型 主机->网络
uint16_t ntohs(uint16_t netshort);//短整型 网络->主机
uint32_t ntohl(uint32_t netlong);//整形 网络->主机
IP地址转换
虽然IP地址本质上是一个整形术,但是在使用的过程中都是通过一个字符串来描述,下面的函数描述了如何将一个字符串类型的IP地址进行大小端转换
下面两个函数均支持IPV4和IPV6
int inet_pton(int af,const char*src,void *dst);
反过来
#include<arpa/inet.h>
const char*inet_ntop(int af,const void *dst ,socklen_t size);//将大端的整型数,转换为小端的点分十进制的IP地址
TCP通信流程
服务器端通信流程
1.创建用于监听的套接字
int lfd=socket();
2.将得到的监听文件描述符和本地的IP端口进行绑定
bind();
3.设置监听(成功之后开始监听,监听的是客户端的连接)
listen();
4.等待并接受客户端的连接请求,建立新的连接,会得到一个新的文件描述符(通信的),没有新连接请求就阻塞
int cfd=accept();
5.通信
read();
write();
6.断开连接,关闭套接字
close();
客户端端通信流程
1.创建一个通信的套接字
int lfd=socket();
2.连接服务器,需要知道服务器绑定的IP和端口
connect();
3.通信
4.断开连接
close();
要先启服务器端的sokect把套接字声明出来,然后再让客户端通信
接收数据的函数
如果连接没有断开,接收端接受不到数据,接受数据的函数会阻塞等待数据到达,数据到达后函数解除阻塞,开始接受数据,当发送端断开连接,接收单无法接收到任何数据,这是就不会阻塞了,函数直接返回
ssize_t read(int sockfd,void *buf,size_t size);
ssize_t recv(int sockfd,void *buf,size_t size,int flags)
发送数据的函数
ssize_t write(int fd,const void *buf,size_t len);
ssize_t send(int fd,const void *buf,size_t len,int flags);
初始化套接字环境
include <winsock2.h>
ws2_32.dll
在windows中使用套接字需要先加载套接字库(套接字环境),最后释放套接字资源
WSAStartup(WORD wVersionRequested,LPWSDATA lpWSAData);
//wVersionRequested指定了请求的Win版本
//lpWSAData是一个指针类型
//调用成功则返回0,调用失败返回SOCKET_ERROR
使用完之后需要注销
int WSACleanup(void)
使用案例:
WSAData wsa;
//初始化套接字
WSAStartup(MAKEWORD(2,2),&wsa);
//...
//注销