【发布时间】:2015-09-20 14:15:05
【问题描述】:
我想使用这个套接字打开连接,Fork 它并保持打开状态,直到连接被我或客户端程序终止。
目前我只能让它打开,然后收到一条消息,然后立即关闭,或者保持打开但不检索任何数据,原因我不知道。
下面的代码主要是教程,但最后我尝试使用 while 循环来读取 select 函数,直到准备好读取消息。然后我只希望它在接收到该字符串时打印该字符串并且不关闭。
我一直在搞乱这段代码,如果我搞砸了,我真的很累很抱歉。
有没有一种方法可以让我创建的 Fork 函数在内部有一个 while(1) 循环,只检查套接字是否接收到消息?
void *socket_handler_thread(void *x_void_ptr)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
}
// loop through all the results and bind to the first we can
for (p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if (p == NULL)
{
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
int socket_fd, result;
fd_set readset;
struct timeval tv;
/* Wait up to five seconds. */
tv.tv_sec = 0;
tv.tv_usec = 100000;
while (1)
{ // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size);
if (new_fd == -1)
{
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *) &their_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
do
{
FD_ZERO(&readset);
FD_SET(new_fd, &readset);
result = select(new_fd + 1, &readset, NULL, NULL, &tv);
printf("Stuck result = %i ::: new_fd = %i \n\r", result, new_fd);
} while (result == -1 && errno == EINTR);
if (result > 0)
{
if (FD_ISSET(new_fd, &readset))
{
if (!fork())
{ // this is the child process
printf("WORKED!");
Fork(sockfd, new_fd);
}
//close(new_fd); // parent doesn't need this
}
result = recv(socket_fd, some_buffer, some_length, 0);
if (result == 0)
{
/* This means the other side closed the socket */
//close(socket_fd);
}
else
{
/* I leave this part to your own implementation */
}
}
else if (result < 0)
{
printf("Connection closed!");
/* An error ocurred, just print it to stdout */
}
}
}
void Fork(int sockfd, int new_fd)
{
int n;
char buffer[256];
bzero(buffer, 256);
close(sockfd); // child doesn't need the listener
if (send(new_fd, "Hello, world!", 13, 0) == -1)
{
perror("send");
}
n = read(new_fd, buffer, 255);
if (n > 0)
{
printf("NOW-> %i ::: %s", n, buffer);
}
close(new_fd);
exit(0);
}
【问题讨论】:
-
有哪些教程?
-
C 区分大小写,所以
fork不是Fork不是FORK。您的命名非常混乱。此外,这绝不是一个可验证的最小示例。 -
正确格式化和缩进你的代码!这种混乱是无法阅读的。也更具体,并提供minimal reproducible example
-
"我好累" 然后睡一觉,明天复习一下今天的代码,看懂了,想想它的作用。做你自己的评论者。
-
fork()是一个众所周知的系统函数。 1) 不要创建与系统函数同名的函数。 2) 不要只用大写来分隔名称,因为这会让代码的人类读者非常困惑。