çpthreads的发送套接字()荷兰国际集团和recv()ING。单独而不是一起工作。不会退出 [英] C pthreads send()ing and recv()ing on a socket. Worked separately but not together. Won't quit

查看:127
本文介绍了çpthreads的发送套接字()荷兰国际集团和recv()ING。单独而不是一起工作。不会退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了平息我对C知识的渴求,在连接到我的家庭网络中的两个Linux机器,我在写一种骨架的telnet的的发送()取值和的recv()取值字符串(只用于插座和线程一些经验)。服务器侦听和客户端连接,并从标准输入发送字符串。我有那些工作,然后我改变了他们实施的pthreads 和线程版本的工作。最后,我把二者连成一个程序,使连接的两端可以(在理论上)发送和接收字符串。无论是客户端和服务器使用的strstr()来观看跳槽,然后退出。作为这篇文章的标题所暗示的,当我把它放在一起,合并后的版本将字符串发送,但是当它应该不会退出。我不知道什么地方出了错。我试图通过它使用gdb步骤,但我使用gdb太缺乏经验,无法判断发生了什么。

那么,为什么不能将其退出?

要那种退一步,有没有实现我想要做的更好的办法?

感谢您的帮助。

clientserver.c

 的#include<&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&;&netdb.h中GT;
#包括LT&; ARPA / inet.h>
#包括LT&; netinet / in.h中>
#包括LT&;&errno.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&pthreads.h中GT;
#包括LT&;&stdlib.h中GT;INT的sockfd = 0,send_running = 1,recv_running = 1,状态= 0,acptsockfd = 0;
焦炭str_to_send [200],str_rcvd [200];
字符* remote_host_addr_str = NULL;
结构SOCKADDR_IN REMOTE_ADDR,listening_addr;void *的发送者(void *的主题ID);void *的接收器(void *的主题ID);INT主(INT ARGC,CHAR *的argv [])
{
的pthread_t线程[2];
长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';
如果(的argc!= 2)
{
    fprintf中(标准错误,\\ n用法:%S<主机的IP连接到大于\\ N的argv [0]);
    返回1;
}
如果((的sockfd =插座(AF_INET,SOCK_STREAM,0))小于0)
{
    fprintf中(标准错误,\\ n套接字错误%S \\ n字符串错误(错误));
    返回1;
}
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(1234);
remote_host_addr_str =的argv [1];
如果(inet_pton(AF_INET,argv的[1],&放大器; remote_addr.sin_addr)下; = 0)
{
    fprintf中(标准错误,\\ n inet_pton错误。\\ n);
    返回1;
}
listening_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listening_addr.sin_port = htons(1234);
状态=在pthread_create(安培;螺纹[T],NULL,接收器(无效*)T);
如果(状态)
{
    fprintf中(标准错误,错误:在pthread_create(接收器)返回%d个\\ N,地位);
    出口(-1);
}
状态=在pthread_create(安培;螺纹[T + 1],NULL,发件人(无效*)T);
如果(状态)
{
    fprintf中(标准错误,错误:在pthread_create(发件人)返回%d个\\ N,地位);
    出口(-1);
}
而(send_running&安培;&安培; recv_running)
    继续;
了pthread_exit(NULL);
返回0;
}void *的发送者(void *的主题ID)
{
如果(连接(的sockfd,(结构sockaddr *)及REMOTE_ADDR,sizeof的REMOTE_ADDR)== -1)
{
    fprintf中(标准错误,套接字错误%S,字符串错误(错误));
    send_running = 0;
}而(1)
{
    与fgets(str_to_send,sizeof的str_to_send,标​​准输入);
    送(的sockfd,str_to_send,sizeof的str_to_send,0);
    如果((的strstr(str_to_send,跳槽))||的strstr(str_rcvd,跳槽))
    {
        send_running = 0;
        recv_running = 0;
        了pthread_exit(NULL);
        打破;
    }
}send_running = 0;
}void *的接收器(void *的主题ID)
{
绑定(的sockfd,(结构sockaddr *)及listening_addr,sizeof的listening_addr);
听(的sockfd,5);
acptsockfd =接受(的sockfd,(结构sockaddr *)NULL,NULL);
而(1)
{
    的recv(acptsockfd,str_rcvd,sizeof的str_rcvd,0);
    如果(str_rcvd [0]!='\\ 0')
        的printf(%S,str_rcvd);
    如果(的strstr(str_rcvd,跳槽))
    {
        关闭(acptsockfd);
        recv_running = 0;
        send_running = 0;
        了pthread_exit(NULL);
        打破;
    }
}
recv_running = 0;
}


解决方案

了pthread_exit 简介


  

隐式调用了pthread_exit()是由当一个线程比其他
  线程在的main()首次调用返回从一开始
  被用于创建它例程。该函数的返回值供应
  作为线程的退出状态。


您在呼唤了pthread_exit()不必要的。如果你能够从你的函数正常返回,则该线程将正常完成。我想preFER如果你能刚刚从函数返回。

我想你会发现 send_running recv_running 标志是多余的。基本上,如果同时发送和接收功能循环,直到他们达到他们的退出条件(跳槽发送或接收),然后他们回来,那么主要功能应该可以等待其他两个线程。看看 在pthread_join 。这将消除忙等待(循环上 send_running和放大器;&安培; recv_running )。在你的主功能

至于为什么该过程不会结束?我不认为接收函数是不断退出,所以这个过程不会结束,直到所有线程都完成。接收机功能仅检查是否跳槽已被接收。如果您发送跳槽,发送功能将正常退出,为的意志为主,但接收方将继续等待接收跳槽的价值。

In order to slake my thirst for C knowledge, on two linux boxes connected to my home network, I'm writing kind of a skeleton telnet that send()s and recv()s strings (just for some experience with sockets and threads). The server listens and the client connects and sends strings from stdin. I got those to work then I changed them to implement pthreads and the threaded versions worked. Last, I put the two together into one program so that either end of the connection could (in theory) send and receive strings. Both the client and server use strstr() to watch for "quit" and then quit. As the title of this post implies, when I put it all together, the combined version will send strings but it doesn't quit when it is supposed to. I'm not sure what went wrong. I tried to step through it with gdb but I'm just too inexperienced with gdb and couldn't tell what is happening.

So, why won't it quit?

To kind of take a step back, is there a better way to implement what I'm trying to do?

Thanks for any help.

clientserver.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;
}

解决方案

From the 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.

You are calling pthread_exit() unnecessarily. If you're able to return from your function normally, then the thread will finish correctly. I would prefer to just return from the function if you can.

I think you'll find that the send_running and recv_running flags are superfluous. Basically, if both the send and receive functions loop until they reach their exit condition ("quit" was sent or received), then they return, then the main function should be able to wait on the other two threads. Look at pthread_join. This will eliminate the busy-waiting (looping on send_running && recv_running) in your main function.

As to why the process doesn't end? I don't think the receiver function is ever exiting, so the process won't end until all threads are finished. The receiver function is only checking to see if "quit" was received. If you send "quit", the sender function will quit normally, as will main, but receiver will continually wait to receive the value "quit".

这篇关于çpthreads的发送套接字()荷兰国际集团和recv()ING。单独而不是一起工作。不会退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆