自己用C语言写了个简单的聊天程序,客户端和服务端能够彼此接受并显示对方发来的消息。使用fork()函数,每个端有两个进程,一个进程用于向对方发送消息,另一个进程接收对方发来的消息。并运用了信号的相关知识识别对方程序是否结束。具体代码如下:
//p2pserver.c #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <error.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 listenfd; // listenfd = socket(PF_INET, SOCK_STREAM, 0); // listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //creat a listen socket if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { ERR_EXIT("socket"); } struct sockaddr_in servaddr; //init the address memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; //#define AF_INET PF_INET //in socket.h servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // inet_aton("127.0.0.1", &servaddr.sin_addr); int on = 1; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { ERR_EXIT("setsockopt"); } //bind the socket if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { ERR_EXIT("bind"); } //set the socket to listen status if (listen(listenfd, SOMAXCONN) < 0) { ERR_EXIT("listen"); } struct sockaddr_in peeraddr; socklen_t peerlen = sizeof(peeraddr); int conn; if ((conn = accept(listenfd, (struct sockaddr * )&peeraddr, &peerlen)) < 0) { ERR_EXIT("accept"); } pid_t pid; pid = fork(); if (pid == -1) { ERR_EXIT("fork"); } if (pid == 0) { //child process, send data signal(SIGUSR1, handler); char sendbuf[1024]; while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { write(conn, sendbuf, strlen(sendbuf)); memset(sendbuf, 0, sizeof(sendbuf)); } printf("child :%d\n", pid); exit(EXIT_SUCCESS); } else { //father process, receive data char recvbuf[1024]; while (1) { memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(conn, recvbuf, sizeof(recvbuf)); if (ret == -1) { ERR_EXIT("read"); } if (ret == 0) { printf("peer close\n"); break; } fputs(recvbuf, stdout); } kill(pid, SIGUSR1); printf("father :%d\n", pid); exit(EXIT_SUCCESS); } close(listenfd); close(conn); return 0; }
//p2pclient.c #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <error.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; // listenfd = socket(PF_INET, SOCK_STREAM, 0); // listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //create a listen socket if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { ERR_EXIT("socket"); } struct sockaddr_in servaddr; //init the address memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // inet_aton("127.0.0.1", &servaddr.sin_addr); if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { ERR_EXIT("connect"); } pid_t pid; pid = fork(); if (pid == -1) { ERR_EXIT("fork"); } if (pid == 0) { char recvbuf[1024]; while (1) { memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(sockfd, recvbuf, sizeof(recvbuf)); if (ret == -1) { ERR_EXIT("read"); } if (ret == 0) { printf("peer close\n"); break; } fputs(recvbuf, stdout); } close(sockfd); kill(getppid(), SIGUSR1); } else { signal(SIGUSR1, handler); char sendbuf[1024] = {0}; while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { write(sockfd, sendbuf, strlen(sendbuf)); memset(sendbuf, 0, sizeof(sendbuf)); } } close(sockfd); return 0; }
文章来源: C语言实现点对点聊天程序