2017-05-04 74 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絕對如此。 –