2011-05-04 4 views
1

Я реализую многопоточное программирование сокетов клиент-сервер в C на одном компьютере с тем же IP-адресом, но с разными портами для клиента и сервера. Я реализовал его с использованием концепций pthread в среде C. Но я вижу, что работает только мой клиентский поток, тогда как мой поток сервера остановился, когда он выполнил процедуру accept(). Мне интересно, что может быть проблемой. Если какой-либо один может узнать, где я делаю ошибку, то это было бы очень полезноМногопоточное программирование сокетов клиент-сервер в C

Мой КЛИЕНТ код выглядит следующим образом:

void *client_connect(void *arg) 
{ 

    int client_socket; 
    struct sockaddr_in Serv_Addr; 
    struct sockaddr_in Client_Addr; 
    int addrlen=sizeof(Client_Addr); 

    char send_buffer_client[] = {"server message"}; 
    char recv_buffer_client[1024]; 
    int nbytes; 

    client_socket = lwip_socket(AF_INET, SOCK_STREAM, 0); 
    if (client_socket < 0) ; 

    memset((char *)&Serv_Addr, 0, sizeof(Serv_Addr)); 
    Serv_Addr.sin_family = AF_INET; 
    Serv_Addr.sin_len = sizeof(Serv_Addr); 
    Serv_Addr.sin_addr.s_addr = inet_addr("1.2.3.4"); 
    Serv_Addr.sin_port = 9999; 
    memset((char *)&Client_Addr, 0, sizeof(Client_Addr)); 
    Client_Addr.sin_family = AF_INET; 
    Client_Addr.sin_len = sizeof(Client_Addr); 
    Client_Addr.sin_addr.s_addr = inet_addr("1.2.3.4"); 
    Client_Addr.sin_port = 5555; 

    lwip_connect(client_socket, (struct sockaddr *)&Serv_Addr, sizeof(Serv_Addr)); 

    while (1) { 

       do{ 
        nbytes = lwip_recv(client_socket, recv_buffer_client, sizeof(recv_buffer_client),0); 
        if (nbytes>0) lwip_send(client_socket, send_buffer_client, sizeof(send_buffer_client), 0); 

        printf("server message = %s\n", recv_buffer_client); 
       } while (nbytes>0); 

       sleep(10); 

     } 
     lwip_close(client_socket); 
} 

Мой SERVER код:

void *server_connect(void *arg) 
{ 

    int server_socket; 
    struct sockaddr_in Serv_Addr; 
    struct sockaddr_in Client_Addr; 
    int addrlen=sizeof(Client_Addr); 
    int clientfd; 
    char send_buffer[] = {"Server message"}; 
    char recv_buffer[1024]; 
    int nbytes_server, client_length; 

    server_socket = lwip_socket(AF_INET, SOCK_STREAM, 0); 
    if (server_socket < 0) 
    printf("could not create server socket"); 
    else 
    printf("created SERVER socket"); 

    memset((char *)&Serv_Addr, 0, sizeof(Serv_Addr)); 
    Serv_Addr.sin_family = AF_INET; 
    Serv_Addr.sin_len = sizeof(Serv_Addr); 
    Serv_Addr.sin_addr.s_addr = inet_addr("1.2.3.4"); 
    Serv_Addr.sin_port = 9999; 


    client_length = sizeof(Client_Addr); 
    if (lwip_bind(server_socket, (struct sockaddr *)&Serv_Addr, sizeof(Serv_Addr)) < 0) {   
      printf("could not BIND"); 
    } 

    if (lwip_listen(server_socket, 20) != 0){ 
      printf("could not BIND"); 
    } 
    while (1) { 
       lwip_accept(server_socket, (struct sockaddr*)&Client_Addr, &client_length);     

       do{ 
       nbytes_server = lwip_recv(server_socket, recv_buffer, sizeof(recv_buffer),0); 
       if (nbytes_server>0){lwip_send(server_socket, send_buffer, sizeof(send_buffer), 0);} 

       printf("client message = %s\n", recv_buffer); 
       }while(nbytes_server>0); 
       sleepms(10); 
     } 
     lwip_close(server_socket); 
} 

void main(void) 
{ 
    pthread_t client_thread; 
    pthread_t server_thread; 

    pthread_create(&server_thread, NULL, server_connect, NULL); 
    pthread_create(&client_thread, NULL, client_connect, NULL); 

    while(1){ 
     sleepms(1); 
     } 
} 

Пожалуйста, дайте мне знаете, если я делаю это неправильный путь

с уважением Deb

+0

вам нужно попробовать переформатировать свой код. Также на стороне клиента, если (client_socket <0); не выглядит правильным. – ColWhi

+1

Во-первых, я бы добавил «\ n» и выходил/возвращался после неудачи printf; код продолжает действовать после ошибок на данный момент. Затем пропустите создание потоков и вызовите server_connect напрямую. Затем попробуйте подключиться через telnet и посмотреть, подключитесь ли вы. –

ответ

0

Если вы находитесь на одной машине, IP-адрес 1.2.3.4, который вы используете, не является типичным адресом для localhost, который должен быть 127.0.0.1. Если вы фактически не сделали IP-адрес устройства с использованием маршрутизатора или каким-либо другим способом IP-адрес 1.2.3.4, этот адрес не будет разрешен, и даже если вы пытаетесь запустить клиент и сервер на том же компьютере, они не найдут друг друга, так как нет способа разрешить 1.2.3.4 данной машине в сети.

Также вам не нужно блокировать сервер для определенного IP-адреса, вы можете просто использовать константу INADDR_ANY от netinet/in.h, которая свяжет сокет с любым интерфейсом в системе. На стороне клиента, хотя вам по-прежнему нужен правильный IP-адрес, но опять же, если это локальный хост, вы можете просто использовать 127.0.0.1.

0

(1) Кажется, что и клиент, и сервер ждут чего-то, прежде чем повторять его. Кто-то должен поговорить первым.

(2) Я не вижу, где ваш lwip_accept возвращает новый сокет, с которым можно связаться с клиентом. Вы в конечном итоге делаете recv/send в прослушивающем сокете.

(3) Также рассмотрим здесь ваш код:

while (1) 
{ 
    lwip_accept(server_socket, (struct sockaddr*)&Client_Addr, &client_length); 

    do 
    { 
     nbytes_server = lwip_recv(server_socket, recv_buffer, sizeof(recv_buffer), 0); 

     if (nbytes_server > 0) 
     { 
      lwip_send(server_socket, send_buffer, sizeof(send_buffer), 0); 
     } 

     printf("client message = %s\n", recv_buffer); 
    } 
    while (nbytes_server > 0); 

    sleepms(10); 
} 

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

(4) Вам не нужны эти вызовы sleepms(). Используйте pthread_join() в основном и просто избавьтесь от остальных. Похоже, что все ваши блоки вызовов блокируются.

2

Вот по крайней мере 3 ошибки:

lwip_accept() возвращает новый дескриптор сокета, вы должны использовать, чтобы прочитать от клиента, а не читать из исходного сокета сервера (обратите внимание также, что lwip_accept будет блокироваться, пока кто-то на самом деле не подключается на сервер).

Ваши номера портов может быть выключен также, если вы на машине Little Endian, они обычно в сетевом порядке байтов, вы должны сделать Serv_Addr.sin_port = htons(9999); и тот же для порта клиента - htons преобразует короткое от хоста к Endian network endian

Вы не отправляете данные!Ваш клиент ждет, когда сервер отправит что-нибудь. Но ваш сервер ничего не отправляет, он ждет, когда клиент что-то пошлет. Ничего не случится.

Проверьте lwip_connect терпит неудачу слишком, и инспектировать errno если среда обеспечивает его, так как это может дать ключ к тому, что идет не так

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