2017-05-04 21 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

メインスレッドで動作します。私はそれが構造体に渡され、アドレスを取得する方法が問題であると思います。 –

+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変数が存在しなくなります。意志

pingServer()のすべての呼び出しによって共有される server_info変数のコピーを作成します
static struct global_table server_info; 
static struct sockaddr_in serveraddr; 

が、その1つのコピー:

一つの修正はserver_infoserveraddr変数staticなどを定義することですあなたのプログラムの生涯にわたって存在します。

+1

私はあなたの要点を得るが、これでも問題は解決しない。実行時にエラーが発生するのは、 "recvfrom:ERROR in Bad address"です。 –

+2

'struct global_table server_info'だけでなく' server_info.serveraddr'が指し示す 'struct sockaddr_in serveraddr'も静的である必要があります。そして、それは、彼が後で 'pingServer()'を複数回呼び出して、一度に複数のスレッドを持つことができなかったことを意味します。 – Dmitri

+0

@ドミトリー絶対に真です。 –

関連する問題