自己用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;
}