accept()功能
系统调用 accept() 这将是一个有点陌生的地方!
你可以想象发生 这种事情:这是非常远离你通过倾听 (listen()) 的port连接 (connect()) 你的机器。它将被添加到等待接收连接 (accept()) 队列 在。
你调用 accept() 告诉它你有空暇的连接。
它将返回一个新的套接字文 件描写叙述符。这样你就有两个套接字了,原来的一个还在侦听你的那个port, 新的在准备发送 (send()) 和接收 ( recv()) 数据。这就是这个过程!
函数是这样定义的:
#include <sys/socket.h>
int accept(int sockfd, void *addr, int *addrlen);
sockfd 相当简单,是和 listen() 中一样的套接字描写叙述符。
addr 是个指向局部的数据结构 sockaddr_in 的指针。
这是要求接入的信息所要去的地 方(你能够測定那个地址在那个port呼叫你)。
在它的地址传递给 accept 之 前,addrlen 是个局部的整形变量。设置为 sizeof(struct sockaddr_in)。
accept 将不会将多余的字节给 addr。假设你放入的少些。那么它会通过改变 addrlen 的值反映出来。
在错误时返回-1。并设置全局错误变量 errno。
如今是你应该熟悉的代码片段。
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MYPORT 3490 /*用户接入端口*/
#define BACKLOG 10 /* 多少等待连接控制*/
main()
{
int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */
struct sockaddr_in my_addr; /* 地址信息 */
struct sockaddr_in their_addr; /* connector's address information */
int sin_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 错误检查*/
my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(MYPORT); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
bzero(&(my_addr.sin_zero),; /* zero the rest of the struct */
/* don't forget your error checking for these calls: */
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
listen(sockfd, BACKLOG);
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, &their_addr, &sin_size);
注意,在系统调用 send() 和 recv() 中你应该使用新的套接字描写叙述符 new_fd。
假设你仅仅想让一个连接进来,那么你能够使用 close() 去关闭原 来的文件描写叙述符 sockfd 来避免同一个port很多其它的连接。
当你第一次调用 socket() 建立套接口描写叙述符的时候。内核就将他设置为堵塞。
假设你不想套接口堵塞,你就要调用函数 fcntl():
通过设置套接口为非堵塞,你可以有效地"询问"套接口以获得信息,可是一般来说轮询不是一个好主意。会浪费cpu时间,
更好的方法是用 select()方法 去查询是否有数据要读进来
select()--多路同步 I/O
select() 同一时间,这样就可以监视多个插座。
假设你想知道,然后他会告诉你哪个插座准备好读,我们正准备写,这在插座异常发生 (exception)。
int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);