系列文章目录
前言
利用socket实现服务器与客户端之间的网络通讯
当子进程结束时会产生SIGCHLD信号,利用该信号实现进程回收
服务端代码
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <wait.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
void recyleChild(int arg)
{
while (1){
int ret = waitpid(-1, NULL, WNOHANG);
if (ret == -1){
break;
}else if (ret == 0){
break;
}else if (ret > 0)
{
printf("子进程%d被回收了\n", ret);
}
}
}
int main()
{
struct sigaction act;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
act.sa_handler = recyleChild;
sigaction(SIGCHLD, &act, NULL);
int lfd = socket(PF_INET, SOCK_STREAM, 0);
if (lfd == -1){
perror("socket");
exit(-1);
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(9999);
saddr.sin_addr.s_addr = INADDR_ANY;
int ret = bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret == -1){
perror("bind");
exit(-1);
}
ret = listen(lfd, 128);
if (ret == -1){
perror("listen");
exit(-1);
}
while (1){
struct sockaddr_in cliaddr;
int len = sizeof(cliaddr);
int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);
if (cfd == -1){
if (errno == EINTR){
continue;
}
perror("accept");
exit(-1);
}
pid_t pid = fork();
if (pid == 0){
char cliIP[16];
inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, cliIP, sizeof(cliIP));
unsigned short cliPort = ntohs(cliaddr.sin_port);
printf("client ip is: %s, port is %d\n", cliIP, cliPort);
char recvBuf[1024];
while (1){
int len = read(cfd, &recvBuf, sizeof(recvBuf));
if (len == -1){
perror("read");
exit(-1);
}else if (len >0){
printf("recv client: %s\n", recvBuf);
}else if (len == 0){
printf("client closed...\n");
break;
}
write(cfd, recvBuf, strlen(recvBuf)+1);
}
close(cfd);
exit(0);
}
}
close(lfd);
}
客户端代码
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <wait.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
int main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1){
perror("socket");
exit(-1);
}
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.110.132", &serveraddr.sin_addr.s_addr);
serveraddr.sin_port = htons(9999);
int ret = connect(fd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
if (ret == -1){
perror("connect");
exit(-1);
}
char recvBuf[1024];
int i = 0;
while (1){
scanf("%s", recvBuf);
// sprintf(recvBuf, "data: %d\n", i++);
write(fd, recvBuf, strlen(recvBuf)+1);
int len = read(fd, recvBuf, sizeof(recvBuf));
if (len == -1){
perror("read");
exit(-1);
}else if (len > 0){
printf("recv server: %s\n", recvBuf);
}else if (len == 0){
printf("server closed...\n");
break;
}
// sleep(1);
}
close(fd);
}

本文档展示了如何使用C语言的socket编程来建立一个简单的TCP服务器,监听9999端口,接收客户端连接并进行数据交互。服务端通过SIGCHLD信号处理子进程回收,确保资源有效释放。客户端则连接到服务器,发送并接收数据。

482

被折叠的 条评论
为什么被折叠?



