Socket编程
Socket
套接字。类似于一个结构体,内部封装了ip地址、协议、端口(唯一标识进程)
阻塞与非阻塞
套接字默认阻塞,即当我们使用某些函数要对缓冲区进行I/O操作时,若缓冲区无法操作,那么会卡在这里直到缓冲区中有空间操作。
对非阻塞套接字,如果行就执行操作并返回成功值,不行就返回错误值。
我们也可以通过以下函数设置非阻塞套接字
int setnonblocking(int fd)
{
int old_option = fcntl(fd, F_GETFL); //获取文件状态
int new_option = old_option | O_NONBLOCK; //添加非阻塞特性
fcntl(fd, F_SETFL, new_option); //设置文件状态
return old_option;
}
监听并接受客户端请求
创建socket
int socket(int domain, int type, int protocol);
domain
:指定协议族,如IPv4、IPv6等等type
:指定套接字类型,如用于 TCP or UDPprotocol
:指定套接字协议,如TCP、UDP
这个函数是创建了一个socket,但要使用这个socket还需要他跟本地ip以及端口绑定,我们还需要创建一个socket地址(不是指针的那种地址),地址内部就包含了ip以及端口号
创建socket地址
struct sockaddr_in listenfd;
memset(&listenfd, 0, sizeof(listenfd)); //固定操作
listenfd.sin_family = AF_INET; //指定协议族
listenfd.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。
listenfd.sin_port = htons(DEFAULT_PORT); //设置的端口 DEFAULT_PORT由我们赋值
socket地址也可叫协议地址
将创建的socket与socket地址绑定
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd
:就是我们创建的socketaddr
:创建的socket地址(协议地址)addrlen
:创建的socket地址的长度
让socket开始监听
int listen(int sockfd, int backlog);
sockfd
:绑定完的完整socketbacklog
:监听队列中最多排几个请求
这一步也叫创建监听队列
接受客户端连接请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd
:我们创建的监听socket,服务器端socketaddr
:客户端的协议地址addrlen
: 客户端的协议地址长度- 返回值:为这个连接分配的文件描述符
accept函数执行成功会自动给addr
以及addrlen
赋值