2014-03-12 84 views
0

我要么很累,不能注意到一些简单的事情,要么就是完全搞砸了我。我遇到了分段错误(核心转储),我已经设法将它指向worker函数中的sendto()。 (服务器)C并发UDP套接字,奇怪的分段错误

Server代码:

//UDPServer.c 

/* 
* gcc -o server UDPServer.c 
* ./server <port> <buffersize> 
*/ 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 


void err(char *str) 
{ 
    perror(str); 
    exit(1); 
} 

int sock; 

typedef struct 
     { 
       struct sockaddr_in client; 
       int buffsize; 
       char *msg; 
     } data; 

void *worker (void* asd) 
{ 
    int len; 
    FILE *fp; 
    data d; 
    d = *(data*) asd; 
    char buff[d.buffsize]; 
    printf("Received packet from %s:%d\nData:%sSize:%d\n", 
       inet_ntoa(d.client.sin_addr), ntohs(d.client.sin_port) 
       ,d.msg,d.buffsize); 


    char * fn; 
    memcpy (fn,d.msg,strlen(d.msg)-1); 
    fp = fopen(fn,"rb"); 
    int bytes; 
    len = sizeof(d.client); 
    printf ("%d\n",len); 

    while (bytes=fread(buff,sizeof(char),d.buffsize,fp)) 
     { 
      printf ("Server sent %d bytes.\n",bytes); 
       -> this if right here. this causes the core dump when attempting to send 
       if(sendto(sock , &buff , sizeof(buff),0,(struct sockaddr *)&d.client,len)<0) 
       err("Error sending."); 

     } 
    fclose(fp); 


} 


int main(int argc, char** argv) 
{ 
    struct sockaddr_in server, client; 
    int port, i; 
    socklen_t slen=sizeof(client); 

    if(argc != 3) 
    { 
     printf("Usage: <Port> <Bytes>\n"); 
     exit(0); 
    } 
    else 
     sscanf(argv[1],"%d",&port); 

    int buffsize = atoi(argv[2]); 

    char buff[buffsize]; 

    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) 
     err("socket"); 
    else 
     printf("Server : Socket() successful\n"); 

    bzero(&server, sizeof(server)); 
    server.sin_family = AF_INET; 
    server.sin_port = htons(port); 
    server.sin_addr.s_addr = htonl(INADDR_ANY); 

    if (bind(sock, (struct sockaddr*) &server, sizeof(server))==-1) 
     err("bind"); 
    else 
     printf("Server : bind() successful\n"); 

    while(1) 
    { 
     memset(&buff,0,sizeof(buff)); 
     if (recvfrom(sock, &buff, sizeof(buff), 0, (struct sockaddr*)&client, &slen)==-1) 
      err("recvfrom()"); 
     data d; 
     d.client = client; 
     d.buffsize = buffsize; 
     d.msg = buff; 

     pthread_t t; 
     pthread_create(&t,NULL,worker,&d); 
     pthread_join(t,NULL); 
    } 

    return 0; 
} 

我不认为客户端是与此有关,因为它是唯一的工作是送的文件名。阅读作品顺便说一句,我测试过了。

无论如何,我只是试图发送文件的内容的那一刻。我一直想弄清楚过去一小时和我的生活,我无法找出它是什么问题。分段错误对我来说毫无意义。

任何建议,非常感谢。

+0

buffsize非常大(例如超过几千字节)?如果是这样,您可能会占用比分配给工作线程更多的堆栈空间。传统的解决方案是分配堆上的缓冲区。 –

回答

1

sendto中我会对sizeof(buff感到紧张。根据参数,buff的大小在运行时固定。 但是 sizeof是编译时操作。 (或者至少是回到过去的好时光 - 我不知道C99) 哦,没关系 - I see that has changed

尽管如此,为什么不使用d.buffsize那里呢?或者可能是bytes,因为你可能没有填充缓冲区。

虽然@ 21Zoo是错误的关于C99动态数组,我认为他发现问题的根源

char * fn; 
memcpy (fn,d.msg,strlen(d.msg)-1); 

fn没有内存分配给复制到,所以你写内存中的随机点。 sendto中的某些内容可能正在绊倒那个现在包含垃圾的内存。

您或者需要malloc(strlen(d.msg)+1)或者使用strdup

+2

这里有很多问题。 'char buff [d.buffsize];'不能这样做,在编译时需要知道数组大小,请使用malloc。 'char * fn;'后面跟着'memcpy(fn,d.msg ...)'也不行,fn还没有初始化。再次,阅读malloc等 – Oliver