學習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;
}
}
}
}