2016-11-15 5 views
0

Я пытался настроить простой чат-сервер UDP, чтобы узнать, как создать свою собственную комнату для чатов, для начала я просто получаю поддержку работы UDP-сервера с клиентами, которые делят тот же IP-порт, что и сервер. Клиенты отправляют данные в виде структуры. Существует 3 возможности, которые должен ожидать сервер, присоединение нового клиента, и он распознает, что, сопоставляя команду JOIN или клиентский выход, сопоставляя команду QUIT или сообщение, не совпадающее ни с одним из них ...UDP-сервер чата с использованием сообщений structs

эти команды хранятся в структуре, которую клиент отправляет в форме, (ID, COMMAND, Domain/Port). , если это не сообщение, это будет (ID, Домен/Порт, Сообщение). Который я обработал в своем коде.

клиент 100% работает так, как он был предоставлен мне в качестве источника, но я не могу использовать его, так как он является исполняемым, поэтому проблема связана с моим сервером. Я сделал инструмент для отладки, чтобы проверить, что происходит не так, похоже, когда клиент присоединяется, и я подтверждаю, что тот клиент, которого я принял, клиент никогда не получает обратно подтверждение, и это потому, что я не форматирую его правильно. Это должно быть что-то вроде Received: <1 JOIN loki>, тогда Sent: <1 JOIN loki>, где 3 переменные с скобками являются частями структуры .. но он не сохраняет 2-ю строку, которая является частью домена/порта правильно ... поэтому, когда я запускаю инструмент отладки, я получаю Received: <1 JOIN>, SENT <1 JOIN>. Так зачем это делать, как будто я разбираю структуру в моей структуре буфера, а затем отправляю ее. Почему он не фиксирует часть домена правильно?

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 
#define LOCAL_PORT 2317 
#define MAX_LEN 255 

struct message { 

    int cid;     /* Connection ID */ 

    char str1[MAX_LEN];   /* JOIN, QUIT, or client-domain-name */ 

    char str2[MAX_LEN];  /* user-string or client-domain-name */ 

}; 



int rcv_cid; 

int rc,sd; 

struct message my_msg, rcv_msg; 

char rcv_str1[MAX_LEN]; 

char rcv_str2[MAX_LEN]; 




int main(int argc, char* argv[]) { 

    struct sockaddr_in servAddr; 
    int servLen = sizeof(servAddr); 
    int IDlist [] = {0,0,0,0,0,0,0,0,0,0} ; 
    int i=0; int port; 
    /* Socket Creation */ 
    if(argc < 3){ 
     printf("usage : ./chatServer <port#> <debug_option:0 or 1>\n"); 
     exit(1); 
    } 
    sd = socket(AF_INET, SOCK_DGRAM , 0); 
    if(sd<0) { 
     printf("%s , cannot open socket \n",argv[0]); 
     exit(1); 
    } 

    /* bind argv[1] server port */ 
    servAddr.sin_family = AF_INET; 
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    /* bind argv[1] which is what the user provides */ 
     port = atoi(argv[1]); 
    servAddr.sin_port = htons(port); 

     rc= bind(sd, (struct sockaddr *) &servAddr , sizeof (servAddr)); 
if(rc <0){ 
    printf("%s: cannot bind port number %d \n", argv[0], port); 
    exit (1); 
} 
printf("%s: waiting for data on port UDP %d \n", argv[0], port); 

while(1) { 
    /* grab incoming request */ 
    rc = recvfrom(sd, &rcv_msg, MAX_LEN, 0, (struct sockaddr *) &servAddr, &servLen); 
    printf(" %s \n" , rcv_msg.str2); 
    if(atoi(argv[2]) == 1){ 
     printf("DEBUG: Receiving <%d %s %s>\n",rcv_msg.cid,rcv_msg.str1,rcv_msg.str2); 
    } 
    if(strcmp(rcv_msg.str1,"join") == 0) { 

     for(i =1; i< 11 ; i ++){ 
      if(IDlist[i] == rcv_msg.cid){ 
       rcv_msg.cid = i; 
       IDlist[i] = rcv_msg.cid; 
       break;} 
     } 



    /*   for(j = 0, j < 10 ; j ++){      */ 
    /*   if(IDlist[j] != IDlist [i]){    */ 

    my_msg.cid = i; 
    strcpy(my_msg.str1, "JOIN"); 
    strcpy(my_msg.str2, rcv_msg.str2);  

    if(atoi(argv[2]) == 1){ 
      printf("DEBUG: Sending <%d %s %s>\n",my_msg.cid,my_msg.str1,my_msg.str2); 
           } 

    rc = sendto(sd, &my_msg, sizeof(my_msg)+1, 0, 
      (struct sockaddr *) &servAddr, 
      sizeof(servAddr)); 
    /* compose a temp struct , then send it to each ID on the list except the one we just added */ 
    } 


if(strcmp(rcv_msg.str1,"QUIT") == 0) { 

    for(i=0;i<10 ; i++){ 
     if(rcv_msg.cid == IDlist[i]) 
      IDlist [i] = 0; 
    } 
    my_msg.cid = rcv_msg.cid; 
    strcpy(my_msg.str1, "QUIT"); 
    strcpy(my_msg.str2, rcv_msg.str2); /*my name Nodname contains domain and port number built into C library */ 

if(atoi(argv[2]) == 1){ 
        printf("DEBUG: Sending <%d %s %s>\n",my_msg.cid,my_msg.str1,my_msg.str2); 
                 } 


    rc = sendto(sd, &my_msg, sizeof(my_msg)+1, 0, 
      (struct sockaddr *) &servAddr, 
      sizeof(servAddr)); 
} 
else { 

my_msg.cid = rcv_msg.cid; 
strcpy(my_msg.str1, rcv_msg.str1); 
strcpy(my_msg.str2, rcv_msg.str2); /*my name Nodname contains domain and port number built into C library */ 

    if(atoi(argv[2]) == 1){ 
       printf("DEBUG: Sending <%d %s %s>\n",my_msg.cid,my_msg.str1,my_msg.str2); 
                } 


rc = sendto(sd, &my_msg, sizeof(my_msg)+1, 0, 
     (struct sockaddr *) &servAddr, 
     sizeof(servAddr)); 

        } 

      } 

     return 0; 
     } 

ответ

0

Вы только позволяют системе читать в наиболее MAX_LEN байт:

rc = recvfrom(sd, &rcv_msg, MAX_LEN, 0, 
    (struct sockaddr *)&servAddr, &servLen 
); 

но rcv_msg более чем в два раза, что размер (это 2 * MAX_LEN + sizeof(int)). Правильно было бы:

rc = recvfrom(sd, &rcv_msg, sizeof(rcv_msg), 0, 
    (struct sockaddr *)&servAddr, &servLen 
); 

servLen Кроме того, должны иметь тип socklen_t и не int; не гарантируется, что оба типа равны или взаимозаменяемы.

И этот код является неправильным, а также:

rc = sendto(sd, &my_msg, sizeof(my_msg)+1, 0, 
    (struct sockaddr *)&servAddr, sizeof(servAddr) 
); 

my_msg точно sizeof(my_msg) большой, так почему бы вам сказать системе посылать sizeof(my_msg)+1 байт? Что это такое +1? Этот один байт находится за концом структуры, он не принадлежит структуре, эта память может быть дополнением или уже принадлежит другой переменной. Вы не должны читать этот байт после структуры, это может даже привести к краху вашей программы, если вам не повезло.

Тогда вам нужно быть осторожным с капитализацией. В коде команды всегда в верхнем регистре («JOIN»), но этот код строки сравнивается с нижней подстроки:

if(strcmp(rcv_msg.str1,"join") == 0) { 

strcmp чувствителен к регистру, strcmp("JOIN", "join") не вернется 0!

И считаете ли вы, что проблема не в том, что приемник не получает сообщение правильно, но отправитель не отправляет сообщение правильно? У меня только код вашего приемника, у меня нет кода отправителя.Вы говорите, что клиент работает так, как вы его получили в исходном коде, но это не значит, что он работает правильно или отправляет данные так, как вы полагаете. Не видя, как клиент отправляет данные, я не могу точно сказать вам точную причину проблемы, и у меня также нет тестового примера для проверки кода сервера.

Если я исправлю все проблемы, о которых говорилось выше, и сделайте сервер для отправки тестового сообщения самому, что отлично работает в моей системе, и вы даже можете проверить этот код непосредственно в Интернете, и там он работает правильно, см. Здесь:

http://rextester.com/MSH79937

+0

Я попытался это, но он все еще не работает :(. –

+0

@ MohammedAl-Huneidi Затем клиент не посылает данные, которые выглядят так, как думают, что это делает. Я нашел еще две ошибки в коде указала выше, но без какого-либо кода клиента, я не могу построить тестовый пример и тестовый случай, я не могу сказать вам, где проблема. – Mecki

+0

@ MohammedAl-Huneidi Также добавлен тестовый пример, где вы может протестировать фиксированный код непосредственно в Интернете, он работает правильно, поэтому, если у вас все еще есть проблемы, вы не правильно добавили все исправления, которые я указал, или ошибка в клиенте. – Mecki

Смежные вопросы