【发布时间】:2021-02-28 22:18:14
【问题描述】:
我正在编写具有 1 个父进程和 3 个子进程的回显服务器。这个服务器的目的是……
- 由函数 fork() 创建的每个子进程都会从每个客户端接收一个字符串。
- 父进程应连接 3 个字符串并发送每个子进程。
- 每个进程都必须将由父进程连接起来的字符串发送给每个客户端。
我尝试过使用 fork、pipe、read 和 write 函数。
我做了两个管道来在孩子和父母之间进行交流。每个子进程都会使用 write 函数来传递一个字符串。为了接收父进程连接的字符串,我编写了源代码
编译执行后发现逻辑错误,只有一个客户端,第一次执行,收到连接字符串,其余两个客户端显示消息“Connection reset by peer”。
我在使用读写函数后关闭了所有管道。我不知道如何处理这个问题。
如何让3个客户端都能正确接收到服务器发送的字符串?
我将附上源代码。
- 服务器代码
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#define MAXLINE 1024
#define PORTNUM 3600
int main(int argc, char **argv)
{
int p1[2];
int p2[2];
pipe(p1);
pipe(p2);
int index = 0;
//char channel[100];
char full_str[MAXLINE];
char recv[MAXLINE];
int isOK1 = 0;
int isOK2 = 0;
int listen_fd, client_fd;
pid_t pid;
socklen_t addrlen;
int readn;
char buf[MAXLINE];
struct sockaddr_in client_addr, server_addr;
if( (listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
return 1;
}
memset((void *)&server_addr, 0x00, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORTNUM);
if(bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) ==-1)
{
perror("bind error");
return 1;
}
if(listen(listen_fd, 5) == -1)
{
perror("listen error");
return 1;
}
signal(SIGCHLD, SIG_IGN);
while(1)
{
addrlen = sizeof(client_addr);
client_fd = accept(listen_fd,
(struct sockaddr *)&client_addr, &addrlen);
if(client_fd == -1)
{
printf("accept error\n");
break;
}
pid = fork();
if(pid == 0)
{
close( listen_fd );
close(p1[0]);
close(p2[1]);
memset(buf, 0x00, MAXLINE);
while((readn = read(client_fd, buf, MAXLINE)) > 0)
{
printf("Read Data %s(%d) : %s\n", inet_ntoa(client_addr.sin_addr), client_addr.sin_port, buf);
write(p1[1], buf, strlen(buf));
close(p1[1]);
wait(NULL);
isOK2 = read(p2[0], recv, MAXLINE);
// When recv read concatenated string by p2 pipe, read function would be executed.
if(isOK2 > 0){
printf("%s I am over\n", recv);
write(client_fd, recv, MAXLINE);
close(p2[0]);
exit(1);
}
memset(buf, 0x00, MAXLINE);
}
close(client_fd);
return 0;
}
else if( pid > 0) {
close(p1[1]);
close(p2[0]);
char channel[100];
if((isOK1 = read(p1[0], channel, 100)>0)){
close(p1[0]);
strcat(full_str, channel);
index++;
full_str[strlen(full_str)] = '\0';
printf("%d \n", index);
printf("%s \n", channel);
printf("%ld \n", strlen(channel));
if(index >= 3) {
write(p2[1], full_str, strlen(full_str));
close(p2[1]);
exit(0);
}
memset(channel, 0x00, 100);
}
//wait(NULL);
}
close(client_fd);
}
return 0;
}
- 客户代码
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MAXLINE 1024
int main(int argc, char **argv)
{
struct sockaddr_in serveraddr;
int server_sockfd;
int client_len;
char buf[MAXLINE];
if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("error :");
return 1;
}
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddr.sin_port = htons(3600);
client_len = sizeof(serveraddr);
if (connect(server_sockfd, (struct sockaddr *)&serveraddr, client_len) == -1)
{
perror("connect error :");
return 1;
}
memset(buf, 0x00, MAXLINE);
read(0, buf, MAXLINE);
buf[strlen(buf)-1] = '\0'; // trim text
if (write(server_sockfd, buf, MAXLINE) <= 0)
{
perror("write error : ");
return 1;
}
memset(buf, 0x00, MAXLINE);
if (read(server_sockfd, buf, MAXLINE) <= 0)
{
perror("read error : ");
return 1;
}
printf("read : %s\n", buf);
close(server_sockfd);
return 0;
}
【问题讨论】: