提问
当我想使用fork()
函数创建子进程来获取socket聊天组时,使用pipe
传递name,ip等。但是pipe(fd)
设置了相同的文件描述符(fd[1] = 4, socket fd = 4
)。因此,如果我想write(fd[1], ....)
将传递给socket fd(4)
如何避免或解决这个问题?
代码
服务器
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <setjmp.h>
#define SERVER_PORT 9098
#define MAX_OR_ADD_LENGTH 100
#define MAX_NAME_SIZE 40
#define MAX_IP_SIZE 20
struct socket_ip_name{
int socket_fd;
char *ip;
char *name;
struct socket_ip_name *prev;
struct socket_ip_name *next;
};
struct record{
int current_length;
struct socket_ip_name *head;
struct socket_ip_name *tail;
int ADDED_LENGTH;
int max_fd_p;
};
struct fd_message{
char message_type[7];
char name[MAX_NAME_SIZE];
char ip[MAX_IP_SIZE];
int socket_fd;
};
jmp_buf for_e;
void initialized_record(struct record *);
void free_record(struct record *);
int main(void){
int fd[2];
if(pipe(fd) == -1){
perror("create pipe error");
}
printf("fd[0] is %d, fd[1] is %d\n", fd[0], fd[1]);
pid_t pid;
int server_fd = socket(AF_INET, SOCK_STREAM, 0), client_fd;
struct record records;
int max_fd_p = 0;
// initialized
initialized_record(&records);
// create
if(server_fd == -1){
perror("create socket descriptor error:");
exit(-1);
}
char message[1024];
struct sockaddr_in server_addr, client_addr;
socklen_t len = sizeof(client_addr);
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_family = AF_INET;
if(inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) != 1){
perror("alloc address error");
exit(-1);
}
if(bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) != 0){
perror("bind error:");
exit(-1);
}
listen(server_fd, 1000);
//
while (1){
client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);
inet_ntop(AF_INET, &client_addr.sin_addr, message, sizeof(message));
if((pid = fork()) == -1){
perror("fork error");
break;
}else if(pid == 0){
close(fd[0]);
close(server_fd);
printf("pipe fd is %d, and socket fd is %d\n", fd[1], client_fd);
printf("Chat subprocess exit\n");
exit(0);
}else{
close(fd[1]);
close(client_fd);
waitpid(pid, NULL, WNOHANG);
}
}
// free function
free_record(&records);
close(server_fd);
exit(0);
}
void initialized_record(struct record *_record){
_record->ADDED_LENGTH = MAX_OR_ADD_LENGTH;
_record->current_length = 0;
_record->head = NULL;
_record->tail = NULL;
_record->max_fd_p = 0;
}
struct socket_ip_name *initialized_sin(int socket_fd, char *ip){
struct socket_ip_name * sin = malloc(sizeof(struct socket_ip_name));
// printf("init state ad ip is %s\n", ip);
sin->socket_fd = socket_fd;
sin->ip = malloc(sizeof(char) * strlen(ip));
if(sin->ip == NULL){
exit(-1);
}
strcpy(sin->ip, ip);
sin->name = NULL;
sin->prev = NULL;
sin->next = NULL;
return sin;
}
void free_record(struct record *_record){
struct socket_ip_name *for_free_pointer = _record->head;
while (_record->head){
_record->head = _record->head->next;
free(for_free_pointer->name);
free(for_free_pointer->ip);
free(for_free_pointer);
for_free_pointer = _record->head;
}
_record->tail = NULL;
_record->current_length = 0;
_record->max_fd_p = 0;
}
客户端
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define SERVER_PORT 9098
int main(void){
int client_fd = socket(AF_INET, SOCK_STREAM, 0);
if(client_fd == -1){
perror("create socket error");
exit(-1);
}
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(SERVER_PORT);
if(inet_pton(AF_INET, "127.0.0.1", &client_addr.sin_addr) == -1){
perror("address error:");
exit(-1);
}
if(connect(client_fd, (struct sockaddr*)&client_addr, sizeof(client_addr)) == -1){
perror("connect error");
exit(-1);
}
char message[1024], input_message[1024];
ssize_t n;
printf("input your name:");
fgets(input_message, 1024, stdin);
if(write(client_fd, input_message, 1024) == -1){
perror("write error");
}
while (1){
memset(message, 0, sizeof(message));
if((n = read(client_fd, message, 1024)) != -1){
if (n == 0){
printf("Get Fin cause from server\n");
break;
}
message[n] = 0;
printf("[server]: %s\n", message);
}
memset(message, 0, sizeof(message));
printf("input message you want to send:");
if(fgets(input_message, 1024, stdin) == NULL){
char *end_message;
if(feof(stdin)){
end_message = "End of file reached\n";
}else{
end_message = "Error occurred\n";
}
if(write(client_fd, end_message, 1024) == -1){
perror("write error");
}
close(client_fd);
break;
}
if(write(client_fd, input_message, 1024) == -1){
perror("write error");
}
}
}
1条答案
按热度按时间bihw5rsg1#
在父节点中调用了
close(fd[1]);
(在第一个请求的末尾),释放了fd 4。要与每个子节点独立通信,您需要为每个子节点使用一个管道。管道应该在循环中创建(在
fork
之前)。下一个问题是,您需要同时侦听传入的连接和传入的数据。为此,您需要使用
select
或类似的。请注意,父级永远不会关闭管道的读端。它需要这样做,因为管道只有在所有 * 四个 * 描述符都关闭后才会关闭。