Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не могу передать данные от одного TCP-клие другому, интерфейс Winsock 2 
:(
    Опции темы
BBulat
Дата 29.1.2009, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 5.12.2006

Репутация: нет
Всего: нет



Использую интерфейс Winsock 2.  Используя пример http://www.citforum.ru/book/cook/winsock.shtml создал 2 TCP-клиента и TCP-сервер. Один клиент передает данные, сервер их принимает и тут же отдает другому клиенту, который должен их принять и вывести на экран. Оба клиента подключаются к одному серверу 127.0.0.1:666. Но на деле этого у меня не получилось. Т.е. удается от одного клиента отсылать данные на сервер и принимать обратно, отправленные сервером данные, этим же клиентом (как и в примере), но не удается принимать данные вторым, подключенным к серверу, клиентом. 

часть кода сервера, отвечающая за прием и передачу данных клиента:
Код

int bytes_recv;
while(  bytes_recv!=SOCKET_ERROR)
{
   bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0)) && bytes_recv;
   send(my_sock,&buff[0],bytes_recv,0);
}

часть кода клиента 1, отвечающая за передачу данных на сервер и за прием ответа от сервера:
Код

int nsize;
    while((nsize=recv(my_sock,&buff[0], sizeof(buff)-1,0))!=SOCKET_ERROR)
    {
      // ставим завершающий ноль в конце строки 
      buff[nsize]=0;

      // выводим на экран 
      printf("S=>C:%s",buff);

      // читаем пользовательский ввод с клавиатуры
      printf("S<=C:"); fgets(&buff[0],sizeof(buff)-1,
             stdin);

      // проверка на "quit"
      if (!strcmp(&buff[0],"quit\n"))
      {
        // Корректный выход
        printf("Exit...");
        closesocket(my_sock);
        WSACleanup();
        return 0;
      }

      // передаем строку клиента серверу
      send(my_sock,&buff[0],nsize,0);
    }


часть кода клиента 2, отвечающая за прием данных от клиента 1, переданных через сервер:

Код

int nsize;
    while((nsize=recv(my_sock,&buff[0],
                      sizeof(buff)-1,0))
                  !=SOCKET_ERROR)
    {
      // ставим завершающий ноль в конце строки 
      buff[nsize]=0;

      // выводим на экран 
      printf("S=>C:%s",buff);
    }


Как правильно организовать передачу от одного клиента другому?

Заранее благодарен!
PM MAIL   Вверх
GremlinProg
Дата 29.1.2009, 22:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



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

кстати, стоит ли перенести обсуждение в раздел C/C++:Сети?

Добавлено через 10 минут и 21 секунду
а )), вижу и код сервера, ну что ж, на сервере в момент подключения клиентов нужно организовывать либо динамический список активных клиентов, среди которых производить широковещательную рассылку или набором команд от клиента организовывать т.н. "диалог" клиентов, опиши, что ты все таки хочешь получить в итоге? что это? чат?

сейчас у тебя взаимодействие клиентов вообще не описано, поэтому клиенты друг друга и не видят, это должно делаться на серверной стороне


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
xvr
Дата 30.1.2009, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Не понял глубокого смысла кода
Код

   bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0)) && bytes_recv;
в сервере. Особенно части && bytes_recv в конце.
Кроме того, безотносительно того, как сервер взаимодействует с клиентами, для общения с 2мя клиентами должно быть как минимум 2 разных сокета, а он у тебя один.

PM MAIL   Вверх
BBulat
Дата 30.1.2009, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 5.12.2006

Репутация: нет
Всего: нет



Цитата(xvr @ 30.1.2009,  12:25)
Не понял глубокого смысла кода
Код

   bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0)) && bytes_recv;
в сервере. Особенно части && bytes_recv в конце.
Кроме того, безотносительно того, как сервер взаимодействует с клиентами, для общения с 2мя клиентами должно быть как минимум 2 разных сокета, а он у тебя один.

ага, там по другому надо) это эхо-сервер, он принимает данные, а потом тут же их отдает.
Код

int bytes_recv;
while( (bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0))!=SOCKET_ERROR)
{
    send(my_sock,&buff[0],bytes_recv,0);
}

Да, сервер создает только один сокет.  Получается мне надо создать второй сокет (my_sock2) с другим портом и уже ему отправлять send(my_sock2,&buff[0],bytes_recv,0)?
PM MAIL   Вверх
xvr
Дата 30.1.2009, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(BBulat @ 30.1.2009,  13:56)
Цитата(xvr @ 30.1.2009,  12:25)

Кроме того, безотносительно того, как сервер взаимодействует с клиентами, для общения с 2мя клиентами должно быть как минимум 2 разных сокета, а он у тебя один.

ага, там по другому надо) это эхо-сервер, он принимает данные, а потом тут же их отдает.

Кому отдает? Тому от кого принял, или кому то другому?
И как он вообще подсоединяется к клиентам - UDP или TCP?
Цитата

Код

int bytes_recv;
while( (bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0))!=SOCKET_ERROR)
{
    send(my_sock,&buff[0],bytes_recv,0);
}

Да, сервер создает только один сокет.  Получается мне надо создать второй сокет (my_sock2) с другим портом и уже ему отправлять send(my_sock2,&buff[0],bytes_recv,0)?
Нет, ему надо делать на своем сокете listen а затем accept в цикле. Каждый выход из accept будет обозначать одного подключенного клиента, при этом accept вернет handle сокета для этого клиента (и они будут разными) [это все для TCP]
Для UDP надо явно каждый раз указывать КОМУ посылается пакет, т.к. UDP протокол соединения не устанавливает, и каждый пакет посылается по явному адресату независимо от остальных

PM MAIL   Вверх
alias_trinity
Дата 2.2.2009, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 10.5.2007

Репутация: 1
Всего: 1



тут есть что надо
PM MAIL   Вверх
BBulat
Дата 2.2.2009, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 5.12.2006

Репутация: нет
Всего: нет



Цитата(xvr @ 30.1.2009,  15:36)
Цитата(BBulat @ 30.1.2009,  13:56)
Цитата(xvr @ 30.1.2009,  12:25)

Кроме того, безотносительно того, как сервер взаимодействует с клиентами, для общения с 2мя клиентами должно быть как минимум 2 разных сокета, а он у тебя один.

ага, там по другому надо) это эхо-сервер, он принимает данные, а потом тут же их отдает.

Кому отдает? Тому от кого принял, или кому то другому?
И как он вообще подсоединяется к клиентам - UDP или TCP?
Цитата

Код

int bytes_recv;
while( (bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0))!=SOCKET_ERROR)
{
    send(my_sock,&buff[0],bytes_recv,0);
}

Да, сервер создает только один сокет.  Получается мне надо создать второй сокет (my_sock2) с другим портом и уже ему отправлять send(my_sock2,&buff[0],bytes_recv,0)?
Нет, ему надо делать на своем сокете listen а затем accept в цикле. Каждый выход из accept будет обозначать одного подключенного клиента, при этом accept вернет handle сокета для этого клиента (и они будут разными) [это все для TCP]
Для UDP надо явно каждый раз указывать КОМУ посылается пакет, т.к. UDP протокол соединения не устанавливает, и каждый пакет посылается по явному адресату независимо от остальных

Я создал второй сокет с тем же адресом, но с другим портом и когда он подключается к серверу, я создаю второй поток, который работает с этим сокетом. 
Часть кода сервера, отвечающая за работу с клиентами:
Код

//Первый сокет(сервер принимает от него данные)
  DWORD WINAPI Сlient(LPVOID client_socket)
  {
    SOCKET my_sock;
    my_sock=((SOCKET *) client_socket)[0];
    #define sHELLO "Hello, Sailor\r\n"
    // отправляем клиенту приветствие
    send(my_sock,sHELLO,sizeof(sHELLO),0);

    
    // цикл сервера: прием данных от клиента и возвращение их этому же клиенту
    while( (bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0))!=SOCKET_ERROR)
    {
            send(my_sock,&buff[0],bytes_recv,0);
    bytes_recv = 0;
    }    

    nclients--; 
    printf("-disconnect\n"); PRINTNUSERS
    closesocket(my_sock);
    return 0;
  }

  //Второй сокет
  DWORD WINAPI Client2(LPVOID client_socket)
  {
    SOCKET my_sock;
    my_sock=((SOCKET *) client_socket)[0];
    #define sHELLO "Hello, Sailor2\r\n"

    send(my_sock,sHELLO,sizeof(sHELLO),0);

    
    // Цикл сервера: передача строки клиенту2
    while(1)
    {
        if(bytes_recv!=0) //глобальная переменная, содержащая количество принятых от первого клиента байт данных 
        {
            send(my_sock,&buff[0],sizeof(buff),0);
        }
    }
  }


В принципе работает, т.е. данные передаются от одного клиента другому, но вместе с полезными данными приходят еще и пустые строки в количестве равном размеру массива buff, т.е. 20 шт.
PM MAIL   Вверх
xvr
Дата 2.2.2009, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



В строке 39 (send(my_sock,&buff[0],sizeof(buff),0);) часть sizeof(buff) заменить на bytes_recv
Кроме того - программа СОВЕРШЕННО не thread-safe, при первом же более менее частом обращении со стороны клиентов начнутся жуткие глюки

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0847 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.