1、Socket编程基础知识概述
(1)头文件
#include<sys/socket.h>//socket/bind/listen/connect/accept等方法的头文件 #include<sys/types.h> #include<arpa/inet.h>//inet_pton #include<netinet/in.h>//sockaddr_in/htons/htonl
(2)数据结构
struct sockaddr_in{ short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; struct in_addr{ unsigned long s_addr; }; struct sockaddr{ unsign short sa_family; char sa_data[14]; };
sockaddr_in与sockaddr所占内存相同,都是16字节。
(3)函数原型
int socket(int domain,int type,int protocol) 成功则返回唯一标识符,失败返回-1 domain:协议族,常见的协议族有AF_INET、AF_INET6、AF_LOCAL、AF_HOST,协议族决定了地址族,即地址的类型,AF_INET指定地址为ipv4,AF_LOCAL指定地址为决定路径。 type:socket类型,常见的有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等 protocol:指定协议。0:TCP
htons(int)/htonl():将主机序转成网络序,htons将端口号转成网络序,利用serv_addr.sin_addr.s_addr=htonl(INADDR_ANY)初始化服务器的地址 inet_pton(int AF,char *src,void *dst):将点分十进制字符串转成网络地址
int bind(int socketfd,struct sockaddr * addr,socksize_t addlen) 将socketfd与地址sockaddr绑定,需要将sockaddr_in 转成sockaddr *;
int listen(int listenfd,int backlog) 成功返回0,失败返回-1 通过socket创建的套接字都是主动的,通过listen函数将其转成被动连接; listenfd是通过socket生成的标识符; backlog是可以排队的最大连接数。 在socket连接中,系统维护两个队列,一个是未完成连接的队列,一个是已完成连接的队列。backlog代表未完成队列的最大长度。例如,设置未完成队列的大小为100,则如果有1000个连接请求时,系统先放100个进入未完成队列,而忽略其他请求,当有请求完成3次握手后,系统会将这个请求从未完成队列中删除放到已完成队列中。
int accept(int listenfd,(struct sockaddr *)clientaddr,socklen_t addrlen) 成功则返回一个连接套接字标识符,失败返回-1
int connect(int clientfd,(struct sockaddr *)servaddr,socklen_t addrlen) 成功返回0,失败返回-1 客户端通过套接字向服务器发起连接请求
收发消息的函数:成功则返回收发消息的字节数,接受完返回0,接收失败返回-1.发送失败返回-1. int write(int connectfd,void* buf,int len) int read(int connectfd,void* buf,int len) int send(int connectfd,void* buf,int bufsize,int flags) int recv(int connectfd,void* buf,int bufsize,int flags) int sendto(int connectfd,void* buf,int bufsize,int flags,(struct sockaddr *) dstaddr,socklen_t addrlen) int recvfrom(int connectfd,void* buf,int bufsize,int flags,(struct sockaddr *) srcaddr,socklen_t addrlen) int sendmessage(int connectfd,(const struct msghdr*) buf,int flags) int recvmessage(int connectfd,(struct msghdr*) buf,int flags)
int close(int fd):关闭套接字,close函数只是将fd的引用计数置为-1,当引用计数变成0的时候才会触发客户端向服务器发送终端连接的请求。
(4)socket编程中的三次握手、四次挥手
- 客户端调用connect函数后,系统向服务器发送SYN请求,此时客户端处于SYN_SEND状态
- 当服务器接收到连接请求,如果accept调用成功,则向客户端发送一个ACK包,此时服务器处于SYN_RCVD
- 客户端收到ACK后,connect函数返回,并向服务器发送ACK,客户端处于ESTABLISHED状态;
- 服务器收到ACK后,accept函数返回,服务器处于ESTABLISHED状态
2、基础练习:编写一个客户端,一个服务端,当服务器收到print request消息时将请求消息打印
参考链接: