Многопоточное программирование клиент-серверных сокетов на C - PullRequest
1 голос
/ 04 мая 2011

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

Мой код КЛИЕНТА выглядит так:

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);
}

Мой код СЕРВЕРА:

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);
        }
}

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

С уважением, Деб

Ответы [ 3 ]

2 голосов
/ 04 мая 2011

Вот как минимум 3 ошибки:

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

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

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

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

0 голосов
/ 04 мая 2011

(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 () в main и просто избавьтесь от всего остального. Похоже, все ваши звонки блокируются.

0 голосов
/ 04 мая 2011

Если вы находитесь на той же машине, 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.

...