一、TCP服务器和客户端的创建
tcp服务器和客户端的创建流程如下图:
服务器端
- socket指定套接字的协议类型,是ipv4还是ipv6,是tcp还是udp;
- bind将socket套接字和服务器地址绑定;
- listen用于开启服务器的监听功能;
- accept用于接收新的客户端的连接,每接收到一个新的客户端,accept都会为其创建一个新的唯一的套接字,并记录客户端的地址;
- recv和send在有客户端连接的情况下使用;
- close关闭指定的套接字对应的客户端的连接;
客户端
- socket指定套接字的协议类型,是ipv4还是ipv6,是tcp还是udp;
- connect指定需要连接的服务器地址;
- 连接成功之后调用recv和send进行数据通信;
- close关闭指定的套接字对应的客户端的连接
二、相关函数
- socket函数
函数原型:int socket(int domain, int type, int protocol);
头文件: #include <sys/types.h>
#include <sys/socket.h>
函数功能:创建一个socket套接字
函数参数:domain指定套接字类型,具体值如下:
AF_UNIX, AF_LOCAL 本地通信 unix(7)
AF_INET IPv4通信协议 ip(7)
AF_INET6 IPv6通信协议 ipv6(7)
AF_IPX IPX互联网分组交换协议
AF_NETLINK 内核和用户空间交互 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)
AF_ALG Interface to kernel crypto API
type指定协议类型,具体值如下:
SOCK_STREAM 提供一种连续的、可信任的、双向的字节流,使用TCP协议需要指定该选项
SOCK_DGRAM 提供一种固定长度的数据报文,使用udp协议需要指定该选项
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 提供数据链路层的原始数据,可以供用户自己实现上层应用协议
SOCK_RDM 提供一种可信赖的数据包传输,但是不保证顺序
SOCK_PACKET Obsolete and should not be used in new programs; see
packet(7).
protocol
这个参数用来给socket指定一个特殊的协议,如IPPROTO_IP、IPPROTO_UDP、IPPROTO_TCP、IPPROTO_ICMP,这个参数通常设置为0,系统会根据前两个参数自动设置具体的协议。
- bind函数
函数原型:int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
函数功能:将socket套接字和地址绑定
函数参数:sockfd 套接字描述符
addr 地址,类型为:
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
3.listen函数
函数原型:int listen(int sockfd, int backlog);
函数功能:这个函数只用在服务器端,用来监听客户端的连接请求,使用backlog指定允许处理的最大连接请求数,如果请求连接的客户端个数超过backlog,请求会被拒绝
函数参数:sockfd 套接字描述符
backlog 最大允许请求连接的客户端数量
4、accept函数
函数原型: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数功能:这个函数只用在服务器端,用于监视是否有新的客户端请求连接,如果有新的客户端连接,accept会为其创建一个新的socket套接字,并唯一标识这个新的客户端与服务器的连接通道。
函数参数:sockfd 套接字描述符
addr 新连接客户端的地址
5、recv、recvfrom和recvmsg
函数原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
函数功能:这三个函数都可以接收网络数据,recv和recvfrom的区别在于recvfrom可以记录发送方的地址,recv相当于recvfrom(sockfd,buf,len,flas,ULL,NULL)
函数参数:sockfd 套接字描述符
buf 接收数据缓冲区
len 缓冲区长度
flas 接收参数,常用值如下:
MSG_DONTWAIT 设置为非阻塞接收,函数调用后不管有没有数据立即返回,默认为阻塞接收
MSG_WAITALL 阻塞接收
MSG_OOB 可以接收和发送带外数据
MSG_PEEK:表示只是从缓冲区读取内容而不清除缓冲区,也就是说下次读取还是相同的内容。
返回值:成功返回接收到的字节数,失败可以通过查询errno的值来获取原因
6、connect函数
函数原型:int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
函数功能:连接指定的服务器
7、send和sendto
函数原型ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
函数功能:发送tcp数据,send只能用于tcp数据的发送,sendto相当于sendto(sockfd, buf, len, flags, NULL, 0);