gpt4 book ai didi

C pthreads send()ing 和 recv()ing 在套接字上。分开工作但没有一起工作。不会退出

转载 作者:太空宇宙 更新时间:2023-11-04 03:57:04 26 4
gpt4 key购买 nike

为了满足我对 C 知识的渴求,在连接到我的家庭网络的两个 linux 机器上,我正在编写一个基本的 telnet,它包含 send()recv( ) 的字符串(只是为了获得套接字和线程的一些经验)。服务器监听,客户端连接并从 stdin 发送字符串。我让它们开始工作,然后我将它们更改为实现 pthreads 并且线程版本工作了。最后,我将两者放在一个程序中,这样连接的任何一端都可以(理论上)发送和接收字符串。客户端和服务器都使用 strstr() 来监视 “quit” 然后退出。正如这篇文章的标题所暗示的,当我将它们放在一起时,组合版本将发送字符串,但它不会按预期退出。我不确定出了什么问题。我尝试使用 gdb 逐步完成它,但我对 gdb 太缺乏经验,无法判断发生了什么。

那么,为什么它不退出呢?

退一步说,有没有更好的方法来实现我正在尝试做的事情?

感谢您的帮助。

客户端服务器.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

int sockfd = 0, send_running = 1, recv_running = 1, status = 0, acptsockfd = 0;
char str_to_send[200], str_rcvd[200];
char *remote_host_addr_str = NULL;
struct sockaddr_in remote_addr, listening_addr;

void *sender(void *threadid);

void *receiver(void *threadid);

int main(int argc, char *argv[])
{
pthread_t threads[2];
long t = 0;

memset(&remote_addr, 0, sizeof remote_addr);
memset(&listening_addr, 0, sizeof listening_addr);
str_to_send[0] = '\0';
str_rcvd[0] = '\0';
if(argc != 2)
{
fprintf(stderr, "\n Usage: %s <IP of host to connect to> \n", argv[0]);
return 1;
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "\n Socket Error %s\n", strerror(errno));
return 1;
}
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(1234);
remote_host_addr_str = argv[1];
if(inet_pton(AF_INET, argv[1], &remote_addr.sin_addr)<=0)
{
fprintf(stderr, "\n inet_pton error \n");
return 1;
}
listening_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listening_addr.sin_port = htons(1234);
status = pthread_create(&threads[t], NULL, receiver, (void *)t);
if(status)
{
fprintf(stderr, "Error: pthread_create(receiver) returned %d\n", status);
exit(-1);
}
status = pthread_create(&threads[t+1], NULL, sender, (void *)t);
if(status)
{
fprintf(stderr, "Error: pthread_create(sender) returned %d\n", status);
exit(-1);
}
while(send_running && recv_running)
continue;
pthread_exit(NULL);
return 0;
}

void *sender(void *threadid)
{
if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof remote_addr) == -1)
{
fprintf(stderr, "socket error %s", strerror(errno));
send_running = 0;
}

while(1)
{
fgets(str_to_send, sizeof str_to_send, stdin);
send(sockfd, str_to_send, sizeof str_to_send, 0);
if((strstr(str_to_send, "quit")) || strstr(str_rcvd, "quit"))
{
send_running = 0;
recv_running = 0;
pthread_exit(NULL);
break;
}
}

send_running = 0;
}

void *receiver(void *threadid)
{
bind(sockfd, (struct sockaddr*)&listening_addr, sizeof listening_addr);
listen(sockfd, 5);
acptsockfd = accept(sockfd, (struct sockaddr *)NULL, NULL);
while(1)
{
recv(acptsockfd, str_rcvd, sizeof str_rcvd, 0);
if(str_rcvd[0] != '\0')
printf("%s", str_rcvd);
if(strstr(str_rcvd, "quit"))
{
close(acptsockfd);
recv_running = 0;
send_running = 0;
pthread_exit(NULL);
break;
}
}
recv_running = 0;
}

最佳答案

来自 pthread_exit synopsis

An implicit call to pthread_exit() is made when a thread other than the thread in which main() was first invoked returns from the start routine that was used to create it. The function's return value serves as the thread's exit status.

您不必要地调用了 pthread_exit()。如果您能够正常地从您的函数返回,那么该线程将正确完成。如果可以的话,我宁愿从函数中返回。

我想您会发现 send_runningrecv_running 标志是多余的。基本上,如果发送和接收函数都循环直到它们达到退出条件(发送或接收到“退出”),然后它们返回,那么主函数应该能够在其他两个线程上等待。看pthread_join .这将消除主函数中的忙等待(在 send_running && recv_running 上循环)。

至于为什么进程没有结束?我认为接收函数永远不会退出,所以在所有线程完成之前进程不会结束。接收器功能仅检查是否收到“退出”。如果发送“quit”,sender 函数将正常退出,main 也是如此,但 receiver 将继续等待接收值“quit”。

关于C pthreads send()ing 和 recv()ing 在套接字上。分开工作但没有一起工作。不会退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15513588/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com