server-api-listen

原型

listen() marks the socket referred to by sockfd as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept(2).

listen()将sockfd套接字标记为被动套接字(监听套接字),用于监听accept的连接请求。

函数原型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// sockfd:
// The sockfd argument is a file descriptor that refers to a socket of type SOCK_STREAM or SOCK_SEQ‐PACKET.
// 要监听的套接字
// backlog:
// The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow. If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.
// 规定内核为此套接字排队的最大连接个数
//
// return:
// On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
// 成功返回0,失败返回-1且会设置errno的值
//
// error:
// EADDRINUSE
// Another socket is already listening on the same port.
// EBADF
// The argument sockfd is not a valid descriptor.
// 参数sockfd非合法socket处理代码
// ENOTSOCK
// The argument sockfd is not a socket.
// EOPNOTSUPP
// The socket is not of a type that supports the listen() operation.
// 指定的socket并未支援listen模式。
int listen(int sockfd, int backlog);

使用参考

支持一个客户端的回射服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>

#define ERR_EXIT(m)\
do\
{\
perror(m); \
exit(EXIT_FAILURE); \
}while (0)

int main(void)
{
int listenfd;
/*if ((listenfd = socket(PF_INET, SOCK_STREAM, 0))<0)*/
if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ERR_EXIT("socket");

struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5188);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/
/*inet_aton("127.0.0.1", &servaddr.sin_addr);*/

int on = 1;
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
ERR_EXIT("SETSOCKOPT") ;

if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
ERR_EXIT("BIND");

if (listen(listenfd, SOMAXCONN) < 0)
ERR_EXIT("LISTEN");

struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int conn;
if ((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)
ERR_EXIT("ACCEPT");

printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));

char recvbuf[1024];
while (1)
{
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
write(conn, recvbuf, ret);
}

close(conn);
close(listenfd) ;

return 0;
}