2017-05-04 80 views
0

我想发送和接收不同的线程。当我使用下面的代码时,我得到一个错误的地址错误,我猜是因为我的服务器地址无法正确传递给线程函数。如何接收和发送不同的线程与C插座

代码:

#include "client.h" 

struct global_table{ 
    struct sockaddr_in *serveraddr; 
    int sockID; 
}; 

void *recvFromServer(struct global_table *rec){ 
    char recBuf[RECVBUFSIZE]; 
    int serverSize = sizeof(rec->serveraddr); 

    while(1) 
    { 
    int n = recvfrom(rec->sockID, recBuf, RECVBUFSIZE, 0, &rec->serveraddr, &serverSize); 
    if (n < 0) 
     perror("ERROR in recvfrom"); 
    decryptData(recBuf); 
    printf("Recieved: %s\n", recBuf); 
    pthread_exit(NULL); 
    } 
} 

void pingServer(char *hostname, int portno) 
{ 
    int sockfd, n, serverlen; 
    struct sockaddr_in serveraddr; 
    struct sockaddr_in client_addr; 
    struct hostent *server; 
    char *buf; 

    sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
    if (sockfd < 0) 
    perror("ERROR opening socket"); 

    server = gethostbyname(hostname); 
    if (server == NULL) 
    perror("ERROR, no host found"); 

    bzero((char *) &serveraddr, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    bcopy((char *)server->h_addr, (char *)&serveraddr.sin_addr.s_addr, server->h_length); 
    serveraddr.sin_port = htons(portno); 

    client_addr.sin_family = AF_INET; 
    client_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    client_addr.sin_port = htons(5500); 

    if (bind(sockfd,(struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1) 
    perror("Socket could not be binded"); 

    if(setsockopt(sockfd,IPPROTO_IP,IP_TOS,&tos,sizeof(tos))) 
    perror("Could not set socket option"); 

    pthread_t threads[2]; 
    serverlen = sizeof(serveraddr); 
    struct global_table server_info; 

    server_info.sockID = sockfd; 
    server_info.serveraddr = &serveraddr; 

    pthread_create(&threads[0],NULL,recvFromServer, &server_info); // Trying to recv on a different thread 
    pthread_join(threads[0],NULL); 

} 

int main(int argc, char **argv) { 
    char *hostname; 
    int portno; 
    if (argc != 3) 
    perror("usage: <hostname> <port>\n"); 

    hostname = argv[1]; 
    portno = atoi(argv[2]); 
    pingServer(hostname, portno); 
    return 0; 
} 

我怎样才能解决这个问题?

+0

它在主线程上工作。我认为它应该传递给struct然后获取地址的方式是有问题的。编译器抱怨, –

+0

在recvfrom调用中看起来太多间接寻址。 '&rec-> serveraddr' shoudl一定是'rec-> serveraddr' – pm100

+0

如果我在主线程上运行一切,代码工作正常。编译时没有错误。 –

回答

1

除了在评论中所指出的问题(和现在,这个问题还注意到在评论...),这条线

struct global_table server_info; 

pingServer()函数创建一个局部变量。

此行

pthread_create(&threads[0],NULL,recvFromServer, &server_info); // Trying to recv on a different thread 
的代码

传递该变量到recvFromServer()功能,这将在不同的线程中运行的地址。但pingServer()立即返回,并且当地的server_info变量不复存在。

一个解决方法是,以限定server_infoserveraddr变量作为static

static struct global_table server_info; 
static struct sockaddr_in serveraddr; 

这将创建将由的pingServer()每次调用被共享的server_info变量一个拷贝,而是一个拷贝将存在于您的程序的整个生命周期中。

+1

我明白你的意思,但仍然不能解决问题。它在运行时说的错误是“错误在recvfrom:错误的地址”。 –

+2

这不仅仅是'struct global_table server_info',而且还有'struct sockaddr_in serveraddr',其中'server_info.serveraddr'指向的那个将需要是静态的。而且,这仍然意味着他不能再多次调用'pingServer()'来一次拥有多个线程。 – Dmitri

+0

@Dmitri绝对如此。 –