Implementing point-to-point chat room under RedHat
Point to point chat room provides a platform for people to communicate, and it has a high degree of privacy and convenience. By providing a perfect network chat system, we can achieve the purpose of communication and contact between people.
development environment
VMware Workstation 15 Pro
Red Hat Enterprise Linux 5
Each person has a computer and can connect to the local area network
Basic functions of the system
(1) Server:
① receive the data sent by the client and display
② accept the data input by the keyboard and send it to the client
③ when the client is closed, all the processes on the server will exit.
(2) Client:
① receive the data sent by the server and display
② accept the data input by the keyboard and send it to the server
③ when the server is shut down, all processes of the client will exit.
Server side programming (p2pserv.c)
#include <stdio.h>//It is the content to be processed before the program is compiled, which is called compile preprocessing command. #include <stdlib.h>//Statement means to include stdlib.h in the program. #include <string.h>//It is the content to be processed before the program is compiled, which is related to the call of string. #include <unistd.h>//The name of the header file that provides access to the POSIX Operating System API. #include <arpa/inet.h>//It mainly defines the format conversion function. #include <sys/socket.h> //Provide socket function and data structure. #include <signal.h>//It defines how to handle different signals when the program executes. /*Error redefinition*/ #define ERR_EXIT(m)\ do\ {\ perror(m);\//Output the cause of the error in the previous function to the standard device. exit(EXIT_FAILURE);\// //Represents an abnormal exit. }while(0) /*Signal processing function*/ void handler(int sig) { printf("recv a sig=%d\n", sig); exit(EXIT_SUCCESS);// //Indicates that the program terminated successfully } /*Start main program*/ int main(int argc,char *argv[]) { int listenfd; //Define listening socket and client socket int connfd; struct sockaddr_in servaddr; struct sockaddr_in clntaddr; socklen_t clntaddr_size; pid_t pid; //Define thread tag variables if(argc!=2) { printf("usage:%s,<port>\n",argv[0]); exit(1); } /*Create server socket*/ listenfd=socket(PF_INET,SOCK_STREAM,0); //Generate a TCP socket if(listenfd==-1) ERR_EXIT("socket"); /*Initialize local address information*/ memset(&servaddr,0,sizeof(servaddr)); //The function is to fill a given value in a block of memory servaddr.sin_family=AF_INET; //When creating a socket, use this field to specify the address family servaddr.sin_addr.s_addr=htonl(INADDR_ANY); //Listen to all addresses of the client servaddr.sin_port=htons(atoi(argv[1])); /*Assign address information to socket*/ if(bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr))==-1) ERR_EXIT("bind"); /*Call the listen function to enter the wait for connection request state. At this time, the socket becomes a passive socket, which is responsible for listening*/ if(listen(listenfd,5)==-1) ERR_EXIT("listen"); /*Call the accept function to take a connection request from the queue header to establish a connection with the client, and return the created socket descriptor, conn_sock is mainly used to communicate with customers, while the previous serv_sock is mainly used for monitoring*/ connfd=accept(listenfd,(struct sockaddr *)&clntaddr,&clntaddr_size); if(connfd==-1) ERR_EXIT("accept"); else printf("recv connect ip=%s,port=%d\n",inet_ntoa(clntaddr.sin_addr),ntohs(clntaddr.sin_port)); //output pid_t pid; pid=fork( );//Create child process if(pid==-1) ERR_EXIT("fork"); if(pid>0) //The parent process is responsible for receiving the data sent by the client { char recvbuf[1024]; while(1) { memset(recvbuf,0,sizeof(recvbuf)); int str_len=read(connfd,recvbuf,sizeof(recvbuf)); if(str_len==-1) ERR_EXIT("read"); if(str_len==0) { printf("Client closed\n"); break; } printf("Message from client:"); fputs(recvbuf,stdout); } close(connfd); close(listenfd); printf("parent close\n"); kill(pid, SIGUSR1); //Call kill function to send signal to subprocess exit(EXIT_SUCCESS); } else if(pid==0) { signal(SIGUSR1, handler);//Once the SIGUSR1 signal is received, the handler function is called for processing char sendbuf[1024]; while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL) { write(connfd,sendbuf,sizeof(sendbuf)); memset(sendbuf,0,sizeof(sendbuf)); } } return 0; }
Client programming (p2pclint.c)
#include <stdio.h>//It is the content to be processed before the program is compiled, which is called compile preprocessing command. #include <stdlib.h>//Statement means to include stdlib.h in the program. #include <string.h>//It is the content to be processed before the program is compiled, which is related to the call of string. #include <unistd.h>//The name of the header file that provides access to the POSIX Operating System API. #include <arpa/inet.h>//It mainly defines the format conversion function. #include <sys/socket.h> //Provide socket function and data structure. #include<signal.h>//It defines how to handle different signals when the program executes. /*Error macro definition*/ #define ERR_EXIT(m)\ //Define error exit do\ {\ perror(m);\ exit(EXIT_FAILURE);\ //On behalf of abnormal exit }while(0) /*Signal processing function*/ void handler(int sig) { printf("recv a sig=%d\n", sig); exit(EXIT_SUCCESS);//Indicates that the program terminated successfully } /*Start main program*/ int main(int argc,char *argv[]) { int sock; struct sockaddr_in servaddr;// Declared a struct sockaddr_in Variable of type char sendbuf[1024];// A sendbuf array of size 1024 is defined if(argc!=3) //Get information error prompt. But don't stop running any code { printf("usage:%s,<IP> <port>\n",argv[0]); exit(1); } /*Create a socket to connect to the server*/ sock=socket(PF_INET,SOCK_STREAM,0); // socket() system call with three parameters if(sock==-1) ERR_EXIT("socket"); memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family=AF_INET; //When creating a socket, use this field to specify the address family. For TCP/IP protocol, it must be set to AF_INTE. servaddr.sin_addr.s_addr=inet_addr(argv[1]); servaddr.sin_port=htons(atoi(argv[2])); /*Establish a connection with the server*/ if(connect(sock,(struct sockaddr *)&servaddr,sizeof(servaddr))==-1) ERR_EXIT("connect"); else printf("Connected......\n"); pid_t pid;// A pid is defined_ Variable pid of type T pid=fork();//The fork() function returns a process number assigned to pid /*The parent process is responsible for receiving data from the keyboard and transmitting it to the server*/ if(pid>0) { signal(SIGUSR1, handler);//Once the SIGUSR1 signal is received, the handler function is called for processing while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL) { write(sock,sendbuf,sizeof(sendbuf)); memset(sendbuf,0,sizeof(sendbuf)); } } /*Subprocess, responsible for receiving data from the server and displaying*/ else if(pid==0) { char recvbuf[1024];// A recvbuf array of size 1024 is defined while(1) { int str_len=read(sock,recvbuf,sizeof(recvbuf)); if(str_len==0) { printf("server closed\n"); break; } else if(str_len<0) ERR_EXIT("read"); printf("Message from server:"); fputs(recvbuf,stdout); memset(recvbuf,0,sizeof(recvbuf)); } close(sock); kill(getppid( ), SIGUSR1);////Call the kill function to send the signal to } else ERR_EXIT("fork"); return 0; }
Operation results
-
Put the edited client "p2pclint.c" file and server "p2pserv.c" file in the created "PTP"_ chat_ Under the "room" folder, as shown in the following figure.
-
Click the right mouse button under this file to pop up the menu, and select "open in terminal" to open the terminal.
-
In the terminal window, enter the gcc command to compile the client and server files.
-
Reopen a terminal window and enter ". / p2pserv 5678" to open the server (5678 is the port number).
-
Reopen a terminal window and input ". / p2pclint 127.0.0.1 5678" to open the client
-
Messages sent in both windows can be received and run successfully.