listen函数一般在调用bind之后-调用accept之前调用。
fd_set
select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。
FD_ZERO(&set); /*将set清零使集合中不含任何fd*/
FD_SET(fd, &set); /*将fd加入set集合*/
FD_CLR(fd, &set); /*将fd从set集合中清除*/
FD_ISSET(fd, &set); /*在调用select()函数后,用FD_ISSET来检测fd在fdset集合中的状态是否变化返回整型,当检测到fd状态发生变化时返回真,否则,返回假(0)*/
select
select()的机制中提供一fd_set的数据结构,实际上是一long类型的数组, 每一个数组元素都能与一打开的文件句柄(不管是Socket句柄,还是其他 文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成, 当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执 行了select()的进程哪一Socket或文件可读。
accept函数
处于监听状态的服务器在获得客户机的连接请求后,会将其放置在等待队列中。当系统空闲时,将接受客户机的连接请求。接收客户机的连接请求使用accept函数,该函数的具体信息如表13.6所示。
表13.6 accept函数头文件
函数形式int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回值成功失败是否设置errno
返回新的套接字文件描述符1是
说明:
accept函数用于面向连接类型的套接字类型(SOCK_STREAM和SOCK_SEQPACKET)。accept函数将从连接请求队列中获得连接信息,创建新的套接字,并返回该套接字的文件描述符。新创建的套接字用于服务器与客户机的通信,而原来的套接字仍然处于监听状态。
accept函数的sockfd参数为监听的套接字描述符。addr参数为指向结构体sockaddr的指针。参数addrlen为addr参数指向的内存空间的长度。
服务器程序
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int server_socket,client_socket;
int server_len,clinet_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int iResult;
fd_set readfds,testfds;
//建立服务器端SOCKET
server_socket = socket(AF_INET,SOCK_STREAM,0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
//将服务器端的SOCKET与端口和IP绑定
bind(server_socket,(struct sockaddr *)&server_address,server_len);
//在服务器端监听客户请求
listen(server_socket,5);
FD_ZERO(&readfds);
FD_SET(server_socket,&readfds);
while(1)
{
char ch;
int fd;
int nread;
testfds = readfds;
printf("server waiting\n");
//监听到客户端消息
iResult = select(FD_SETSIZE,&testfds,(fd_set *)0,(fd_set *)0,(struct timeval *) 0);
if(iResult < 1)
{
printf("server error\n");
exit(-1);
}
for(fd = 0; fd < FD_SETSIZE; fd++)
{
if(FD_ISSET(fd,&testfds))
{
if(fd == server_socket)
{
clinet_len = sizeof(client_address);
client_socket = accept(server_socket,(struct sockaddr *)&client_address,( socklen_t *)&clinet_len);
FD_SET(client_socket,&readfds);
printf("addding client on fd %d\n",client_socket);
}
else
{
ioctl(fd,FIONREAD,&nread);
if(nread == 0)
{
close(fd);
FD_CLR(fd,&readfds);
printf("remoing client on fd %d\n",fd);
}
else
{
read(fd,&ch,1);
sleep(5);
printf("sering client on fd %d\n",fd);
ch++;
write(fd,&ch,1);
}
}
}
}
}
return 0;
}
客户端程序#include
#include
#include
#include
#include
#include
#include
int main()
{
int sockfd;
int len;
struct sockaddr_in address;
int result;
char ch = 'A';
sockfd = socket(AF_INET,SOCK_STREAM,0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(9734);
len = sizeof(address);
//将客户端的SOCKET与服务器端口进行链接
result = connect(sockfd,(struct sockaddr *)&address,len);
if(result == -1)
{
printf("connect error\n");
exit(-1);
}
write(sockfd,&ch,1);
read(sockfd,&ch, 1);
printf("char from server = %c \n",ch);
close(sockfd);
exit(0);
}