P2p chat and linuxp2p chat in Linux
Implementation Details of p2p chat in Linux
Do one thing at a time, and do well.
Today, I am free to write a P2P point-to-point chat program. I think it is useful for beginners of network programming. Let's not talk about it. Let me paste the code first. There are several points to consider. I will write it after the code. The end of the Code download article.
Server. c
# Include <stdio. h> # include <sys/types. h> # include <sys/socket. h> # include <stdlib. h> # include <netinet/in. h> # include <arpa/inet. h> # include <unistd. h> # include <string. h> # include <signal. h>
# Define ERR_EXIT (m) \ do \ {\ perror (m); \ exit (EXIT_FAILURE); \} while (0) void do_something (int conn) {char recvbuf [1024]; for (;) {memset (recvbuf, 0, sizeof (recvbuf); int ret = read (conn, recvbuf, sizeof (recvbuf )); if (ret = 0) {printf ("client closed! \ N "); break;} else if (ret =-1) {ERR_EXIT (" read ");} fputs (recvbuf, stdout); write (conn, recvbuf, ret) ;}} void handler (int sig) {printf ("recv a sig = % d \ n", sig); exit (EXIT_SUCCESS);} int main () {int listenfd; if (listenfd = socket (AF_INET, SOCK_STREAM, 0) <0) ERR_EXIT ("socket"); int on = 1; int ret = setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, & on, sizeof (on); struct sockaddr_in servaddr; memset (& s Ervaddr, 0, sizeof (servaddr); servaddr. sin_family = AF_INET; servaddr. sin_port = htons (10001); servaddr. sin_addr.s_addr = htonl (INADDR_ANY); if (bind (listenfd, (struct sockaddr *) & servaddr, sizeof (servaddr) <0) ERR_EXIT ("bind "); if (listen (listenfd, SOMAXCONN) <0) // active socket to passive socket ERR_EXIT ("listen"); struct sockaddr_in peeraddr; socklen_t socklen = sizeof (peeraddr ); int conn; pid_t pid; if (conn = ac Cept (listenfd, (struct sockaddr *) & peeraddr, & socklen) <0) // obtain the active socket ERR_EXIT ("accept"); printf ("ip: % s port: % d \ n ", inet_ntoa (peeraddr. sin_addr), ntohs (peeraddr. sin_port); pid = fork (); char sendbuf [1024] = {0}; if (pid =-1) ERR_EXIT ("pid "); if (pid = 0) {signal (SIGUSR1, handler); while (fgets (sendbuf, sizeof (sendbuf), stdin )! = NULL) {write (conn, sendbuf, strlen (sendbuf); memset (sendbuf, 0, sizeof (sendbuf);} printf ("child closed \ n "); exit (EXIT_SUCCESS);} else {char recvbuf [1024]; while (1) {memset (recvbuf, 0, sizeof (recvbuf); int ret = read (conn, recvbuf, sizeof (recvbuf); if (ret =-1) ERR_EXIT ("read"); else if (ret = 0) {printf ("peer close \ n "); break;} fputs (recvbuf, stdout);} printf ("kill parent! \ N "); kill (pid, SIGUSR1); exit (EXIT_SUCCESS); // do_something (conn);} close (conn); close (listenfd ); exit (0 );}
#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <arpa/inet.h>#include <signal.h>#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)void handler(int sig){ printf("recv a sig = %d\n",sig); exit(EXIT_SUCCESS);}int main(int argc,char *argv[]){ int sockfd; if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) ERR_EXIT("socket"); struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(10001); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0) ERR_EXIT("connect"); char sendbuf[1024] = {0}; char recvbuf[1024] = {0}; pid_t pid; pid = fork(); if(pid == -1) ERR_EXIT("fork"); if(pid == 0) { while(1) { memset(recvbuf,0,sizeof(recvbuf)); int ret = read(sockfd,recvbuf,sizeof(recvbuf)); if(ret == -1) ERR_EXIT("read"); else if (ret == 0) { printf("peer closed\n"); break; } fputs(recvbuf,stdout); } printf("child close\n"); kill(pid,SIGUSR1); exit(EXIT_SUCCESS); } else { signal(SIGUSR1,handler); while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL) { write (sockfd,sendbuf,strlen(sendbuf)); memset(sendbuf,0,sizeof(sendbuf)); } printf("parent close!\n"); } close(sockfd); exit(0);}
The implementation of the function is very simple, but pay attention to the following details:
1. After connecting C and S, when S is closed, C is still not closed, and I use the signal function.
Implementation Method: when the parent process is closed, the child process is also closed. When the child process is closed, the parent process is also closed.
2. One thread is used to listen and one thread is used to wait for input. This is a small multi-threaded program.
Create a sub-process. C-end, sub-process listening, the parent process is waiting for input. Opposite to send.
3. semaphore problems:
SIGUSR1: the User-Defined semaphore. handler is used to kill the process and exit.
Program testing:
Conclusion: In general, this is very simple, that is, whether several functions are flexibly applied. Note: If the read function is not read, it will be blocked. If a 0 value is received, it means that the other party closes the program and then exits the program.
Download Code: GitHub
Statement: The level is limited. If something is wrong or wrong, I hope the majority of users will correct it.