Linux C網路程式設計 ————6、IO複用併發伺服器程式設計
阿新 • • 發佈:2019-01-07
伺服器端程式碼實現
#include<stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #define PORT 1234 #define BACKLOG 5 #define MAXDATASIZE 1000 typedef struct { int fd; char *name; struct sockaddr_in addr; char *data; }CLIENT; void process_cli(CLIENT *client,char * recvbuf,int len); void savedata(char *recvbuf,int len,char data); main() { int i ,maxi,maxfd,sockfd; int nready; ssize_t n; fd_set rset,allset; int listenfd,connectfd; struct sockaddr_in server; CLIENT client[FD_SETSIZE]; char recvbuf[MAXDATASIZE]; int sin_size; if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("Creating socket failed."); exit(1); } int opt=SO_REUSEADDR; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1) { perror("Bind error."); exit(1); } if(listen(listenfd,BACKLOG)==-1) { perror("listen() error\n"); exit(1); } sin_size=sizeof(struct sockaddr_in); maxfd=listenfd; maxi=-1; for(i=0;i<FD_SETSIZE;i++) { client[i].fd=-1; } FD_ZERO(&allset); FD_SET(listenfd,&allset); while(1) { struct sockaddr_in addr; rset=allset; nready=select(maxfd+1,&rset,NULL,NULL,NULL); if(FD_ISSET(listenfd,&rset)) { if((connectfd=accept(listenfd,(struct sockaddr *)&addr,&sin_size))==-1) { perror("accept() error"); continue; } for(i=0;i<FD_SETSIZE;i++) if(client[i].fd<0) { client[i].fd=connectfd; client[i].name=malloc(char[MAXDATASIZE]); client[i].addr=addr; client[i].data=malloc(char[MAXDATASIZE]); client[i].name[0]='\0'; client[i].data[0]='\0'; printf("You got a connection from %s",inet_ntoa(client[i].addr.sin_addr)); break; } if(i==FD_SETSIZE) FD_SET(connectfd,&allset); if(connectfd>maxfd) maxfd=connectfd; if(i>maxi) maxi=i; if(--nready<=0) continue; } for(i=0;i<=maxi;i++) { if((sockfd=client[i].fd)<0) continue; if(FD_ISSET(sockfd,&rset)) { if((n=recv(sockfd,recvbuf,MAXDATASIZE,0))==0) { close(sockfd); printf("Client(%s) closed connection.User's data:%s\n",client[i].name,client[i].data); FD_CLR(sockfd,&allset); client[i].fd=-1; free(client[i].name); free(client[i].data); } else process_cli(&client[i],recvbuf,n); if(--nready<=0) break; } } } close(listenfd); } void process_cli(CLIENT * client,char * recvbuf,int len) { char sendbuf[MAXDATASIZE]; recvbuf[len-1]='\0'; if(strlen(client->name)==0) { memcpy(client->name,recvbuf,len); printf("Client's name is %s.\n",client->name); return; } printf("Received client(%s) message:%s\n",client->name,recvbuf); savedata(recvbuf,len,client->data); for(int il=0;il<len-1;il++) { sendbuf[il]=recvbuf[len-il-2]; } sendbuf[len-1]='\0'; send(client->fd,sendbuf,strlen(sendbuf),0); } void savedata(char *recvbuf,int len,char *data) { int start =strlen(data); for(int i=0;i<len;i++) { data[start+i]=recvbuf[i]; } }
客戶端程式碼實現
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT 1234 #define MAXDATASIZE 100 void process(FILE *fp,int sockfd); char* getMessage(char* sendline,int len,FILE* fp); int main(int argc,char *argv[]){ int sockfd; struct hostent *he; struct sockaddr_in server; if (argc!=2){ printf("Usage:%s<IP Address>\n",argv[0]); exit(1); } if((he=gethostbyname(argv[1]))==NULL){ printf("gethostbyname() error\n"); exit(1); } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){ printf("socket() error\n"); exit(1); } bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr=*((struct in_addr *)he->h_addr); if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1){ printf("connect() error\n"); exit(1); } process(stdin,sockfd); close(sockfd); } void process(FILE *fp,int sockfd){ char sendline[MAXDATASIZE],recvline[MAXDATASIZE]; int num; printf("Connected to server.\n"); printf("Input client's name:"); if(fgets(sendline,MAXDATASIZE,fp)==NULL){ printf("\nExit.\n"); return; } send(sockfd,sendline,strlen(sendline),0); while(getMessage(sendline,MAXDATASIZE,fp)!=NULL){ send(sockfd,sendline,strlen(sendline),0); if((num=recv(sockfd,recvline,MAXDATASIZE,0))==0){ printf("Server terminated.\n"); return; } recvline[num]='\0'; printf("Server Message:%s\n",recvline); } printf("\nExit.\n"); } char* getMessage(char* sendline,int len,FILE* fp){ printf("Input string to server:"); return(fgets(sendline,MAXDATASIZE,fp)); }