如果客户端有连接请求,必须使用下述函数来接受客户端的请求。
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
addr用于存放客户端的地址,addrlen在调用函数时被设置为addr指向区域的长度,在函数调用结束后被设置为实际地址信息的长度。本函数会阻塞等待知道有客户端请求到达。
返回值是一个新的套接字描述符,它代表的是和客户端的新的连接,可以把它理解成是一个客户端的socket,这个socket包含的是客户端的ip和port信息 。(当然这个new_socket会从sockfd中继承 服务器的ip和port信息,两种都有了),而参数中的SOCKET s包含的是服务器的ip和port信息 。
于是之后的send和recv函数中的fd都是指这个 new_fd,也就是
int send(int new_fd, const void *msg, int len, int flags);
int recv(int new_fd, void *buf, int len, unsigned int flags);
即参数其实都是目标fd(就是记录了客户端的信息 ),说明服务器是从客户端接收或者发送给客户端的。这个和文件的操作FILE *fp =fopen(); fwrite(fp,xx,xx,xx);是差不多的,这里的fp代表的也是目标即目标文件名。
这样,客户端的 connect函数 ,
int connect (int sockfd, struct sockaddr *serv_addr, int addrlen);
这里的sockfd 就把客户端的ip和port ,服务器的ip和port信息都有了。所以之后的 send(),recv()都有信息了。
----------------------------------------------------------------------------------------------------------------------------------------------------------
accept()函数
准备好了,系统调用 accept() 会有点古怪的地方的!你可以想象发生 这样的事情:有人从很远的地方通过一个你在侦听 (listen()) 的端口连接 (connect()) 到你的机器。它的连接将加入到等待接受 (accept()) 的队列 中。你调用 accept() 告诉它你有空闲的连接。它将返回一个新的套接字文 件描述符!这样你就有两个套接字了,原来的一个还在侦听你的那个端口, 新的在准备发送 (send()) 和接收 ( recv()) 数据。这就是这个过程!