多路转接模型服务器和客户端的实现

来源:互联网 发布:windows script engine 编辑:程序博客网 时间:2024/06/06 03:26
/* 多路转接模型 *//* 服务器的实现 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <arpa/inet.h>#include <ctype.h>#define portnumber 8000  //宏定义端口号#define MAX_LTNE 80/*处理函数:Myfunc();  功能:将大写字符转换成小写字符  参数:为需要转换的字符    */ void Myfunc(char *p){/* 空字符串 */if(NULL == p){return ;}/* 判断字符串,并进行转换 */for(; *p != '\0';p++){if(*p >= 'A'  &&  *p >= 'Z'){*p = *p -'A' + 'Z';}}}int main(){/* 变量定义 */int lfd,cfd,sfd,rdy;int i,len,n;int opt = 1;   //套接字选项int client[FD_SETSIZE];  //客户端连接套接字描述数组int ret;struct sockaddr_in sin;struct sockaddr_in cin;int maxi;int maxfd;    //最大连接数fd_set rset;fd_set allset;socklen_t addr_len;   //地址结构长度char buf[MAX_LTNE];char addr_p[20];/* 对server_addr_in 结构进行赋值 */bzero(&sin,sizeof(struct sockaddr_in));   //清零sin.sin_family = AF_INET;sin.sin_addr.s_addr = htonl(INADDR_ANY); //表示能接收任何地址,将IP地址转成网络字节序sin.sin_port = htons(portnumber);   //将端口号转成网络字节序/* 调用socket函数创建一个TCP协议套接字 */lfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == lfd){perror("socket");exit(1);}/* 设置套接字,使用默认选项 */setsockopt(lfd, SOL_SOCKET , SO_REUSEADDR ,&opt,sizeof(opt) );/* 调用bind函数,绑定套接字 */ret = bind(lfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr));if(-1 == ret){perror("bind");exit(2);}/* 开始监听端口,等待客户端请求 */ret = listen(lfd,20);if(-1 == ret){perror("listen");exit(3);}printf("\nAccepting connections ... \n");maxfd = lfd;maxi = -1;    //对最大文件描述符初始化/* 初始化客户端连接描述符集合 */for(i = 0;i < FD_SETSIZE;i++){client[i] = -1;}FD_ZERO(&allset);  //清空文件描述符集合FD_SET(lfd,&allset);  //将监听字设置在集合内/* 开始服务程序的while循环 */while(1){rset = allset;//得到当前可以读的文件描述符数rdy = select(maxfd + 1,&rset,NULL,NULL,NULL);if(FD_ISSET(lfd,&rset)){addr_len = sizeof(sin);/* 接收客户端的请求 */cfd = accept(lfd,(struct sockaddr*)(&cin),&addr_len);if(-1 == cfd){perror("accept");exit(4);}/* 查找一个空闲位置 */for(i = 0;i < FD_SETSIZE;i++){if(client[i] <= 0){client[i] = cfd;  //将处理该客户端的套接字设置到该位置break;}}/* 太多的客户端连接,服务器拒绝请求,跳出循环 */if( i == FD_SETSIZE){printf("Too many clients!\n");exit(5);}FD_SET(cfd,&allset);   //设置连接集合if(cfd < maxfd)    //新的连接描述符{maxfd = cfd;}if(i < maxi){maxi = i;}if(--rdy <= 0)   // 减少一个描述符{continue;}}/* 对每一个连接描述符做处理 */for(i = 0;i < FD_SETSIZE;i++){sfd = client[i];if(sfd < 0){continue;}if(FD_ISSET(sfd,&rset)){n = read(sfd,buf,MAX_LTNE);printf("%s\n",buf);if(0 == n){printf("The other side has been closed !\n");fflush(stdout);  //刷新终端close(sfd);FD_CLR(sfd,&allset);   //清空连接描述符client[i] = -1;}else{/* 将客户端地址转换成字符串 */inet_ntop(AF_INET,&cin.sin_addr,addr_p,sizeof(addr_p));addr_p[strlen(addr_p)] = '\0';/* 打印客户端地址和端口号 */printf("Client IP is %s  Port is %d  \n",addr_p,ntohs(cin.sin_port));Myfunc(buf);  //调用字符串大小转换函数n = write(sfd,buf, n+1);/* 写函数出错 */if(n == 1){exit(6);}}/* 如果没有套接字可读,退出循环 */if(--rdy <= 0){break;}}}}/* 关闭套接字 */close(lfd);return 0;}



/* 客户端的实现 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#define portnumber 8000int main(int argc , char *argv[]){int nbytes,ret;int sockfd;char buf[80],buf2[80];struct sockaddr_in server_addr;struct hostent *host;if(argc != 2){printf("Input error! Please input a hostname!\n");exit(1);}host = gethostbyname(argv[1]);if(NULL == host){printf("Gethostname error");exit(2);}/* 调用socket 函数创建一个socket套接字 */sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("Socket error");exit(3);}bzero(&server_addr,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(portnumber);server_addr.sin_addr = *((struct in_addr*)host->h_addr);/* 连接服务器 */ret = connect(sockfd,(struct sockaddr*)(&server_addr), sizeof(struct sockaddr));if(-1 == ret){perror("connect");exit(4);}while(1){printf("Please input char :\n");fgets(buf,1024,stdin);write(sockfd,buf,strlen(buf));nbytes = read(sockfd , buf2 ,81);if(-1 == nbytes){perror("read");exit(5);}buf2[nbytes] = '\0';printf("\nClient received from Server %s \n",buf2);}/* 关闭套接字 */close(sockfd);return 0;}

后记:学而思,思而问,问而后多敲代码