1. 创建socket
- #include <sys/types.h>
- #include <sys/socket.h>
- int socket(int domain, int type, int protocol);
type参数指定服务类型:SOCK_STREAM(流服务,TCP协议),SOCK_DGRAM(数据报,UDP协议)。
protocol参数是在前两个参数构成的协议集合下,再选择一个具体的协议。不过这个值通常都是唯一的(前两个值已经完全决定了它的值)。几乎在所有情况下都设置为0, 表示使用默认协议。
调用成功返回一个socket文件描述符,失败返回-1,并设置errno
2. bind函数
- #include <sys/types.h>
- #include <sys/socket.h>
- int bind(int socket, struct sockaddr* my_addr, socklen_t addrlen);
bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样
3. 监听socket listen
- #include <sys/socket.h>
- int listen(int sockfd, int backlog);
创建一个监听队列以存放待处理的客户连接。
listen函数在一般在调用bind之后-调用accept之前调用,它的函数原型是:
#include<sys/socket.h>
int listen ( int sockfd, int backlog )
int listen ( int sockfd, int backlog )
参数sockfd是被listen函数作用的套接字
参数backlog是侦听队列的长度。
在进程正在处理一个连接请求的时候,可能还存在其它的连接请求。因为TCP连接是一个过程,所以可能存在一种半连接的状态,有时由于同时尝试连接的用户过多,使得服务器进程无法快速地完成连接请求。如果这个情况出现了,服务器进程希望内核如何处理呢?内核会在自己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理的连接(还没有调用accept函数的连接),这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限。这个backlog告诉内核使用这个数值作为上限。
返回值 | 成功 | 失败 | 是否设置errno |
0 | −1 | 是 |
错误信息:
EADDRINUSE:另一个socket也在监听同一个端口。
EBADF:参数sockfd为非法的文件描述符。
ENOTSOCK:参数sockfd不是文件描述符。
EOPNOTSUPP:套接字类型不支持listen操作。
- #include <sys/types.h>
- #include <sys/socket.h>
- int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen);
sockfd参数是执行过listen调用的监听socket。
addr参数用来获取被接受连接的远端socket地址,该地址的长度由addrlen参数指出。
调用成功时返回一个新的连接socket,该socket唯一标识了被接受的这个连接,服务器可通过读写该socket来与客户端通信; 失败时返回-1,并设置errno。