「ネットワークアプリケーションの設計」-チャットルーム



Network Application Design Chat Room



これは15年間の実地試験です。見ないでください。
16日は ワードゲーム
参考です。

//Server #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PORT 5000 // Listening port #define SIZE sizeof(X) // The size of structure X typedef struct xinxi // Structure xinxi, alias X { char id[20] // Unique id for each account char passwd[20] //account password char name[50] // Account nickname int online // 0 is offline, 1 is online int fd // Store the new socket generated by accept after the client successfully connects, offline is -5 struct xinxi *next // The first address of the next linked list }X // The global variable of the structure head address is easy to call X* head=NULL // The number of accounts and the number of saved information respectively int count=0 int zhzx(char id[20])// Function declaration // Used to save account information void baocun() { FILE *fp fp=fopen('123','w') // Save under the current running server file 123 if(fp==NULL) { printf('open error ') return } printf('count=%d',count) fwrite(&count,sizeof(int),1,fp) // First save the number of accounts X* p p=head if(p->next==NULL) // If the account list is empty, close the file and exit the function { fclose(fp) return } p=p->next while(p) // Save account information by structure size { fwrite(p,sizeof(X),1,fp) p=p->next } printf('Account information saved successfully n') fclose(fp) } // Create a header pointer for account information and read and save the registered account information from the file X * create() { X* x x=(X*)malloc(SIZE) if(x==NULL) { printf('create error ') return NULL } x->next=NULL FILE* fp fp=fopen('123','a+') // Open the file and read the record if(fp==NULL) { printf('open error ') return NULL } if(fgetc(fp)==EOF) // If the file is empty, return the head pointer { fclose(fp) return x } rewind(fp) // The file pointer returns to the file header int n fread(&n,sizeof(int),1,fp) // First read the length count=n // Global variable gets account length X t X *p,*p1 int i for(i=0i<ni++) // Read information according to the length of the account structure { fread(&t,sizeof(X),1,fp) p1=x while(p1->next) { p1=p1->next } p=(X*)malloc(sizeof(X)) // Each time create a new account structure size space to store information p->next=NULL strcpy(p->id,t.id) // Account, nickname, password, friends and number of friends read and save strcpy(p->name,t.name) strcpy(p->passwd,t.passwd) p->fd=-5 // Each server new connection word is set to -5 p->online=0 // Set online status to offline p1->next=p } fclose(fp) return x } // Determine whether the string is all numbers, return 1 instead of 0 int isnum1(char s[20]) { int i=0 while(s[i]) { if(!isdigit(s[i])) return 0 i++ } return 1 } void add(int fd) // Register function function { X *p1,*p,*p2 int leap=0 // Identifier, whether the account can be registered correctly p=(X*)malloc(SIZE) // Open a space of the size of the account information structure if(p==NULL) return char str[256] char str1[256] memset(str,0,256) memset(str1,0,256) strcpy(str,'Please enter the account number (pure number) you want to register') send(fd,str,strlen(str),0) memset(str,0,256) recv(fd,str,256,0) strcpy(str1,str) if(!isnum1(str)) // Judge whether it is a pure digital account { memset(str,0,256) strcpy(str,'Please enter a pure digital account! N') send(fd,str,strlen(str),0) return } p1=head while(p1->next) { if(strcmp(p1->next->id,str)==0) { leap=1 break } p1=p1->next } if(leap==1) { memset(str,0,256) strcpy(str,'Duplicate account n') send(fd,str,strlen(str),0) return } // Register account information and assign initial value strcpy(p->id,str1) memset(str,0,256) strcpy(str,'Please enter password') send(fd,str,strlen(str),0) memset(str,0,256) recv(fd,str,256,0) strcpy(p->passwd,str) memset(str,0,256) strcpy(str,'Please enter a nickname') send(fd,str,strlen(str),0) memset(str,0,256) recv(fd,str,256,0) strcpy(p->name,str) p1=head while(p1->next) { p1=p1->next } p1->next=p p->online=0 p->fd=-5 p->next=NULL memset(str,0,256) strcpy(str,'Registration succeeded n') send(fd,str,strlen(str),0) count++ // Number of global variable accounts +1 baocun() // Save the account information once in the file } int yzzh(char id[20])// Verify that the id exists { X *p int leap=0 // The head node of the account information structure begins to traverse if(head->next==NULL) return 0 p=head->next while(p) { if(strcmp(id,p->id)==0) return 1 p=p->next } return 0 } int yzmm(char id[20],char passwd[20])// Verify that passwd exists { X *p int leap=0 if(head->next==NULL) return 0 p=head->next while(p) { if(strcmp(id,p->id)==0&&strcmp(passwd,p->passwd)==0) return 1 p=p->next } return 0 } //edit personal information void xgnc(int fd,char id[20]) { X *p,*p1 int i char fa[1024] char shou[1024] memset(fa,0,1024) memset(shou,0,1024) p=head->next while(p) { if(strcmp(p->id,id)==0) break p=p->next } sprintf(fa,'My nickname:% s nMy account:% sMy password:% s',p->name,p->id,p->passwd) send(fd,fa,strlen(fa),0) memset(fa,0,1024) strcpy(fa,' t1. Change nickname n t2. Change password') send(fd,fa,strlen(fa),0) recv(fd,shou,1024,0) if(strcmp(shou,'1')==0) // Enter 1 to modify the nickname { memset(fa,0,1024) strcpy(fa,'Please enter a new nickname') send(fd,fa,strlen(fa),0) memset(shou,0,1024) recv(fd,shou,1024,0) strcpy(p->name,shou) baocun() return } else if(strcmp(shou,'2')==0) // Enter 2 to change the password { memset(fa,0,1024) strcpy(fa,'Please enter a new password') send(fd,fa,strlen(fa),0) memset(shou,0,1024) recv(fd,shou,1024,0) strcpy(p->passwd,shou) baocun() // Save once return } else { memset(fa,0,1024) strcpy(fa,'Illegal input') send(fd,fa,strlen(fa),0) return } } int zhzx(char id[20])// Verify that the account is online { X* p p=head while(p) { if((strcmp(p->id,id)==0)&&p->online==1) return 1 // Online return 1 p=p->next } return 0 } char a[100][20] // Put the id of the chat room person int len=0 // Number of chat rooms // Create a multiplayer chat room void duorenliao(int fd,char id[20]) { system('play -q 11.wav repeat 2') // Play a prompt tone to enter the chat room char fa[1024] char shou[1024] char nichen[20]={'dashabi'} strcpy(nichen,id) memset(fa,0,1024) memset(shou,0,1024) strcpy(fa,'You have entered the chat room, enter stop to exit, enter look to view the current chat room staff') send(fd,fa,strlen(fa),0) strcpy(a[len],id) len++ // For each person entering, add 1 to the length int i X* p time_t timep time(&timep) // Time function p=head->next while(p) { if(strcmp(p->id,nichen)==0) { strcpy(nichen,p->name) break } p=p->next } while(1) // Basic information for creating chat rooms { memset(shou,0,1024) recv(fd,shou,1024,0) if(strcmp(shou,'stop')==0) // stop to exit the chat room { for(i=0i<leni++) { if(strcmp(a[i],id)==0) { while(i<len-1) { strcpy(a[i],a[i+1]) i++ } } } len-- for(i=0i<leni++) { p=head->next while(p) { if(strcmp(p->id,a[i])==0) { memset(fa,0,1024) sprintf(fa,'% s quit chat room',nichen) send(p->fd,fa,strlen(fa),0) break } p=p->next } } return } if(strcmp(shou,'look')==0) // look to see how many people are in the chat room and display their nickname and account { memset(fa,0,1024) sprintf(fa,'There are% d people in the current chat room. They are:',len) send(fd,fa,strlen(fa),0) for(i=0i<leni++) { p=head->next while(p) { if(strcmp(p->id,a[i])==0) { memset(fa,0,1024) sprintf(fa,'The nickname is% s and the account is% s',p->name,p->id) send(fd,fa,strlen(fa),0) break } p=p->next } } continue } for(i=0i<leni++) // The message sent to everyone in the chat room { p=head->next while(p) { if(strcmp(p->id,a[i])==0&&strcmp(p->id,id)!=0) { memset(fa,0,1024) time(&timep) sprintf(fa,'%s%s say: %s',ctime(&timep),nichen,shou) send(p->fd,fa,strlen(fa),0) break } p=p->next } } } } // The concurrent server uses threads to complete void * handleclient(void * newfd) { int fd=(int)newfd int evi=1 char recvbuf[1024] char recvbuf1[1024] char sendbuf[1024] memset(recvbuf,0,sizeof(recvbuf)) memset(recvbuf1,0,sizeof(recvbuf1)) memset(sendbuf,0,1024) if(recv(fd,recvbuf,1024,0)==-1) { perror('recv') //Error message return } else { printf('Client:% s n',recvbuf) // tcp three-way handshake rule, reply to the client } while(1) { evi=1 memset(sendbuf,0,1024) // Interface after login strcpy(sendbuf,'Welcome to use this service, the available functions are as follows n t1. Login account n t2. Register account n tquit. Sign out n') send(fd,sendbuf,strlen(sendbuf),0) memset(recvbuf,0,sizeof(recvbuf)) recv(fd,recvbuf,1024,0) if(strcmp(recvbuf,'1')==0) // Received the client input as 1, please enter the login account { memset(sendbuf,0,1024) strcpy(sendbuf,'Please enter the login account') // Require client to enter account password if(send(fd,sendbuf,strlen(sendbuf),0)==-1) { perror('send') return } memset(recvbuf,0,sizeof(recvbuf)) if(recv(fd,recvbuf,1024,0)==-1) { perror('recv') return } memset(sendbuf,0,sizeof(sendbuf)) strcpy(sendbuf,'Please enter your password') if(send(fd,sendbuf,strlen(sendbuf),0)==-1) { perror('send') return } memset(recvbuf1,0,sizeof(recvbuf1)) if(recv(fd,recvbuf1,1024,0)==-1) { perror('recv') return } // The matching account passwords exist and are correct if(yzzh(recvbuf)==0||yzmm(recvbuf,recvbuf1)==0) { memset(sendbuf,0,1024) strcpy(sendbuf,'Incorrect account or password entered n') send(fd,sendbuf,strlen(sendbuf),0) } else if(zhzx(recvbuf)==1) { memset(sendbuf,0,1024) strcpy(sendbuf,'This account is online') send(fd,sendbuf,strlen(sendbuf),0) } else { strcpy(recvbuf1,recvbuf) memset(sendbuf,0,1024) strcpy(sendbuf,'Login successful n') X*p p=head while(p->next) { if(strcmp(p->next->id,recvbuf1)==0) { p->next->online=1 p->next->fd=fd break } p=p->next } send(fd,sendbuf,strlen(sendbuf),0) // Functions available after login while(1) { memset(sendbuf,0,1024) strcpy(sendbuf,'The functions you can use are as follows n t1. Group chat n t2. View or modify personal information n t3. Exit n') send(fd,sendbuf,strlen(sendbuf),0) memset(recvbuf,0,sizeof(recvbuf)) if(recv(fd,recvbuf,1024,0)==-1) { perror('recv') return } else if(strcmp(recvbuf,'1')==0)// Enter the multiplayer chat room { duorenliao(fd,recvbuf1) } else if(strcmp(recvbuf,'2')==0)// View or modify personal information { xgnc(fd,recvbuf1) } else if(strcmp(recvbuf,'3')==0)// Exit, and set the online information to zero, and the socket value to -5 { p=head while(p->next) { if(strcmp(p->next->id,recvbuf1)==0) { p->next->online=0 p->next->fd=-5 break } p=p->next } break } } } } else if(strcmp(recvbuf,'2')==0) { add(fd) } else if(strcmp(recvbuf,'quit')==0) { memset(sendbuf,0,1024) strcpy(sendbuf,'Welcome to use, thank you') send(fd,sendbuf,strlen(sendbuf),0) break } else { continue } } close(fd) } // Determine whether the client is still online void * panduan(void) { X* p char fa[1024] p=head while(1) // Determine whether to disconnect, if disconnect this account to be offline, listen socket-5 { p=head->next while(p) { if(p->online==1) { struct tcp_info info int len=sizeof(info) getsockopt(p->fd,IPPROTO_TCP,TCP_INFO,&info,(socklen_t*)&len) if((info.tcpi_state!=TCP_ESTABLISHED)) { p->online=0 p->fd=-5 } } p=p->next } } } int main() { int sockfd=0,newfd=0 // Define and initialize int chlid=0 int ret=0 int len=sizeof(struct sockaddr) struct sockaddr_in myaddr struct sockaddr_in otheraddr memset(&myaddr,0,len) memset(&otheraddr,0,len) // Realize port reuse int reuse = 1 sockfd = socket(AF_INET, SOCK_STREAM,0) if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { perror('setsockopet error ') return -1 } // Initialize the structure myaddr.sin_family = AF_INET myaddr.sin_port = htons(PORT) myaddr.sin_addr.s_addr=htonl(INADDR_ANY) //myaddr.sin_addr.s_addr=INADDR_ANY can automatically obtain the local ip address // Binding socket if(-1==(bind(sockfd,(struct sockaddr*)&myaddr,len))) { perror('Binding error:') //Error message return -1 } else { printf('Binding socket successful! N') } // Start listening if((listen(sockfd,10))==-1) { perror('Listening error:') return -1 } else { printf('Successful monitoring! N') } printf('Server waiting ... n') pthread_t id1,id2 head=create() // Create the head node of account information while(1) { if((newfd=accept(sockfd,(struct sockaddr*)&otheraddr,&len))==-1) { perror('accept') return -1 } else // Connect successfully and output client information { printf('Client connected successfully') printf('--Client IP address =% s, port number =% d n',inet_ntoa(otheraddr.sin_addr),ntohs(otheraddr.sin_port)) } // Thread client pthread_create(&id1,NULL,handleclient,(void*)newfd) // Determine whether the client is still online pthread_create(&id2,NULL,(void*)panduan,NULL) pthread_detach(id1)// Disconnect the thread, the resource system automatically recycles after the thread ends pthread_detach(id2) } close(sockfd) return 0 } // Client #include #include #include #include #include #include #include #include #include #include #include #include #define PORT 5000 int n=0 // The global variable n controls the couple's real-time chat output on the first line int leap=0 // Control thread shou1 to run int leap1=0 // Control thread fa to run // Used to control the input and output positions of the screen void handle(char str[1024],int people) { char str1[1024] memset(str1,0,1024) n++ // Control the output on the first few lines printf('33[0m33[s') // Save the current cursor sprintf(str1,'33[0m33[%d1H',n) printf(str1) // The cursor jumps to the nth line of the current screen // printf (' 033 [0m 033 [1 1H') // The cursor jumps to the first line, the first frame if(strcmp(str,'over')==0) // over will not print and end the function return if(people==0) // People control the output of local user input information or the other party's information printf('me say:%s ',str) else printf('%s ',str) printf('33[0m33[u') // Resume the cursor fflush(stdout) // Clear the standard output buffer in the I / O buffer to restore the cursor to the origin if(n>=9) { system('clear') // Clear screen printf('33[0m33[201H')// The cursor jumps to the twentieth line printf('Enter: ') // Main process input printf('33[0m33[K') // Empty the current line where the cursor starts n=0 // Output more than 9 lines and return to 0 } } // The shou1 thread receives real-time chat information for two people void* shou1(void* newfd) { while(leap==1) // Global variables control the thread { int fd=(int)newfd char shou[1024] memset(shou,0,1024) recv(fd,shou,1024,0) if(strcmp(shou,'over')==0) // If it is not over, the screen will be printed after receiving break handle(shou,1) // The first parameter is a string, the second if it is 0 local input, 1 foreign input } } // shou thread receives server messages void* shou(void* newfd) { int fd=(int)newfd int ret=0,ret1=0 char shou[1024] char fa[1024] int people=0 // people equal to 0 is local news, 1 is foreign news while(1) { memset(shou,0,1024) if((ret=recv(fd,shou,1024,0))==-1) return else puts(shou) if(ret==0) { printf('Server failure n') exit(0) } } } // fa thread is used to send information to the server void* fa(void* newfd) { int fd=(int)newfd char fa[1024] while(1) { if(leap1==0)// If leap1 == 0, it means that the two-person chat room is established and this thread is suspended { memset(fa,0,1024) scanf('%s',&fa) if(send(fd,fa,strlen(fa),0)==-1) return if(strcmp(fa,'chat')==0)// Send chat to request to establish a double chat room { leap1=1 } if(strcmp(fa,'end')==0)// Send end to end the client program { printf('Welcome to goodbye n') close(fd)// Close the socket exit(0) } } } } int main() { int sockfd=0// Define and initialize int ret=0 int len=sizeof(struct sockaddr) struct sockaddr_in otheraddr memset(&otheraddr,0,len) // tcp socket connection if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror('sockfd') return -1 } else { printf('Socket connection successful ...% d n',sockfd) } // Initialize the structure, put the server ip address and port number otheraddr.sin_family = AF_INET otheraddr.sin_port = htons(PORT) otheraddr.sin_addr.s_addr=htonl(INADDR_ANY) //connect to the server if(connect(sockfd,(struct sockaddr*)&otheraddr,len)==-1) { perror('connect') return -1 } else { printf('connection succeeded...') printf('--IP address of server =% s, port number =% d n',inet_ntoa(otheraddr.sin_addr),ntohs(otheraddr.sin_port)) } // Create thread pthread_t id1,id2 char recvbuf[1024] char sendbuf[1024] memset(recvbuf,0,sizeof(recvbuf)) memset(sendbuf,0,1024) // Send information to the server, handshake to determine whether to establish a connection strcpy(sendbuf,'Here is the client n') if(send(sockfd,sendbuf,strlen(sendbuf),0)==-1) { perror('send') return -1 } if(recv(sockfd,recvbuf,1024,0)==-1) { perror('recv') return -1 } else { printf('Server:% s n',recvbuf) } // Start the sending and receiving function of the client thread pthread_create(&id2,NULL,fa,(void*)sockfd) pthread_create(&id1,NULL,shou,(void*)sockfd) // Wait for the sending thread to end and exit the client pthread_join(id2,NULL) return 0 }