C/C++ TCP网络通信基本流程
通信流程如下:
服务端:
- 调用socket函数创建socket(监听socket)
- 调用bind函数将socket绑定到某个IP和端口
- 调用listen函数开启监听
- 当有客户端请求连接上来时,调用accept函数接收连接,产生一个新的socket
- 基于新的socket调用recve或者send函数,开始与客户端进行数据交互
- 通信结束后,调用close函数关闭监听socket
客户端:
- 调用socket函数创建客户端socket
- 调用connect函数尝试连接服务器
- 连接成功后调用send或recv函数,开始与服务器进行数据交互
- 通信结束后,调用close函数关闭监听socket
如下图所示
socket函数族
-
int socket(int domain, int type, int protocol);
功能:创建通信端点并返回描述符
参数domain: 指定通信域; 这将选择用于通信的协议族。协议族包含如下
Name Purpose Man page AF_UNIX, AF_LOCAL Local communication unix(7) AF_INET IPv4 Internet protocols ip(7) AF_INET6 Pv6 Internet protocols ipv6(7) AF_IPX IPX - Novell protocols AF_NETLINK Kernel user interface device netlink(7) AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7) AF_AX25 Amateur radio AX.25 protocol AF_ATMPVC Access to raw ATM PVCs AF_APPLETALK Appletalk ddp(7) AF_PACKET Low level packet interface packet(7) 参数type: 指定的类型,该类型指定通信语义。类型有:
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length). SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer is required to read an entire packet with each input system call. SOCK_RAW Provides raw network protocol access. SOCK_RDM Provides a reliable datagram layer that does not guarantee ordering. SOCK_PACKET Obsolete and should not be used in new programs; see packet(7). 前两个分别对应TCP和UDP类型的socket
参数protocol: 指定协议,常用有IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC,协议和socket的类型要匹配。0会选择type对应的默认类型。一般写0。
-
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:连接服务器
sockfd:socket套接字
addr: 一个地址结构体的const指针,指向要绑定给sockfd的地址,结构体的结构和地址协议相符
ipv4的地对应的
struct sockaddr_in { sa_family_t sin_family; /*地址族: AF_INET */ in_port_t sin_port; /*网络字节序的端口号 */ struct in_addr sin_addr; /*internet 地址 */ }; /* Internet 地址. */ struct in_addr { uint32_t s_addr; /* 网络字节序的地址 */ };
addrlen: addr结构体的长度
-
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:将socket绑定到某个IP和端口
sockfd:为 socket()函数创建返回的fd
addr:指向一个包含了ip地址 端口等信息
addrlen:sockaddr的长度
成功返回0,失败返回-1
-
int listen(int s, int backlog);
s:要监听的socket的描述符
backlog:指定未完成连接队列的最大长度
-
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:接收连接,产生一个新的socket
sockfd:服务器socket描述字
addr:获取的客户端的ip地址、端口信息和协议族等信息
addrlen:addr长度
返回值:新连接客户端套接字的描述符