学习Linux c,首先需要写的是一个基于tcp的网络调用server,下面逐个注释分析代码逻辑。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#define SERV_PORT 6677
#define LENGTH_OF_LISTEN_QUEUE 20
#define MAXLINE 100
int main(int argc, char **argv)
{
int i,maxi,maxfd,listenfd,connfd,sockfd;
int nready,client[FD_SETSIZE];
/*
/usr/include/sys/types.h
*/
ssize_t n;
/*
/usr/include/sys/select.h
可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符
*/
fd_set rset, allset;
char buf[MAXLINE];
/*
/usr/include/netinet/in.h
*/
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
/*
/usr/include/sys/socket.h
*/
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if( listenfd < 0 )
{
printf("create socket failed!\n");
exit(1);
}
/*
/usr/include/strings.h
*/
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
{
printf("server bind port %d failed!\n", SERV_PORT);
exit(1);
}
if(listen(listenfd, LENGTH_OF_LISTEN_QUEUE))
{
printf("Server Listen Failed!\n");
exit(1);
}
maxfd = listenfd;
maxi = -1;
for(i = 0; i < FD_SETSIZE; i++)
client[i] = -1;
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
for(;;)
{
rset = allset;
/*
负值:select错误 正值:某些文件可读写或出错 0:等待超时,没有可读写或错误的文件
*/
nready = select(maxfd+1, &rset , NULL , NULL, NULL);
//printf("nready:%d\n", nready);
printf("maxfd:%d\n", maxfd);
if(FD_ISSET(listenfd, &rset))
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
for(i = 0; i< FD_SETSIZE; i++)
{
if(client[i] < 0){
client[i] = connfd;
break;
}
}
if (i == FD_SETSIZE)
{
printf("too many clients\n");
exit(1);
}
FD_SET(connfd, &allset);
if(connfd > maxfd)
/* int maxfd是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1 */
maxfd=connfd;
if(i > maxi)
maxi = i;
if(--nready <= 0)
continue;
}
for (i = 0; i<=maxi; i++)
{
if((sockfd = client[i]) < 0)
continue;
if(FD_ISSET(sockfd, &rset))
{
/*从socket读取内容*/
if((n = read(sockfd, buf, MAXLINE)) == 0)
{
close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
}else
{
/*把内容写入socket*/
write(sockfd, buf, n);
}
if( --nready <= 0 )
break;
}
}
}
}