Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Отправка/получение инфы через сокеты, Помогите найти проблему 
:(
    Опции темы
Timkin
Дата 10.10.2005, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 30.8.2005
Где: Кёльн, Германия

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



Привет всем!
Такая проблема: написал 2 программы - клиент и хост. Клиент коннектится к хосту и посылает данные через сокет. Хост разрешает соединение и получает данные.
Вот коды программ:
Клиент:
Код

#include <stdio.h>
#include <windows.h>

int main(void)
{
    WSADATA WsaDat;
    if (WSAStartup(MAKEWORD(1,1),&WsaDat)!=0)
      printf("WSA Initialization failed.");     
    SOCKET Socket; 
    Socket = socket(AF_INET,SOCK_STREAM,0);
    if (Socket==INVALID_SOCKET) 
      printf("Socket creation failed.");
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port = 3500;
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.S_un.S_un_b.s_b1 = 192; 
    SockAddr.sin_addr.S_un.S_un_b.s_b2 = 168; 
    SockAddr.sin_addr.S_un.S_un_b.s_b3 = 178; 
    SockAddr.sin_addr.S_un.S_un_b.s_b4 = 22;
    if (connect(Socket,(SOCKADDR *)(&SockAddr),sizeof(SockAddr))!=0) 
      printf("Failed to establish connection with server.\n");
    char buf[200];
    printf("Enter the text to send: ");
    scanf("%s",buf);
    send(Socket,buf,strlen(buf)+1,0);
    system("PAUSE");
    return EXIT_SUCCESS;
}

Хост:
Код

#include <windows.h>
#include <stdio.h>

int main(void)
{
    WSADATA WsaDat;
    if (WSAStartup(MAKEWORD(1,1),&WsaDat)!=0) 
      printf("WSA Initialization failed."); 
    SOCKET Socket; 
    Socket = socket(AF_INET,SOCK_STREAM,0);
    if (Socket==INVALID_SOCKET)
      printf("Socket creation failed.");
    char Name[255];
    gethostname(Name,255); 
    HOSTENT *HostInfo;
    HostInfo = gethostbyname(Name);
    if (HostInfo==NULL) 
      printf("Attempt to retreive computer information failed.");
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port = 3500;
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)HostInfo->h_addr_list[0][0]; 
    SockAddr.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)HostInfo->h_addr_list[0][1]; 
    SockAddr.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)HostInfo->h_addr_list[0][2]; 
    SockAddr.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)HostInfo->h_addr_list[0][3];
    if (bind(Socket,(SOCKADDR *)(&SockAddr),sizeof(SockAddr))==SOCKET_ERROR) 
      printf("Attempt to bind failed.");
    listen(Socket,1);
    SOCKET TempSock = SOCKET_ERROR; 
    while (TempSock==SOCKET_ERROR) 
      TempSock = accept(Socket,NULL,NULL);
    Socket = TempSock;
    int RetVal = SOCKET_ERROR; 
    char String[50]; 
    while (true) {
      RetVal = recv(Socket, String, 255, 0);
      if (RetVal!=SOCKET_ERROR)   
        printf("\n%s",String);
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}

То есть хост выводит на экран то, что получил от клиента.
Когда я запускаю клиента в первый раз - всё ОК. Когда запускаю во второй раз, он уже ничего не передаёт (на экране хоста ничего не отображается). Когда запускаю в третий раз, он выводит сообщение, что не может соединиться с хостом...
Кто-нибудь может подсказать, в чём тут проблема?
PM MAIL WWW ICQ   Вверх
Plamenk
Дата 11.10.2005, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Дело в том, что ты жестко связываешь свой TempSocket с первым клиентом:

Код

   SOCKET TempSock = SOCKET_ERROR; 
    while (TempSock==SOCKET_ERROR) 
      TempSock = accept(Socket,NULL,NULL);


Поэтому все остальные клиенты и не могу связаться с сервером. Для каждого клиента должен быть свой accept (По-моему, данное верно только для TCP).
PM MAIL   Вверх
Timkin
Дата 11.10.2005, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 30.8.2005
Где: Кёльн, Германия

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



Ну я не очень силён в сокетах... Это же тот же самый клиент, просто после того, как окно с прогой закрывается, я запускаю его заново.
Насколько я понял, после того, как получены данные с клиента, первым обратившегося к серверу, порт не освобождается, и остальные клиенты вынуждены выстраиваться в очередь.smile
Как после получения данных сбросить клиента и заняться следующим? Или если моё предположение неверно, как изменить код хоста так, чтобы он постоянно принимал данные с любого клиента? Помоги, плз!!!

Это сообщение отредактировал(а) Timkin - 11.10.2005, 12:10
PM MAIL WWW ICQ   Вверх
Mad
Дата 11.10.2005, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

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



Timkin
Тебе надо организовать несколько потоков
общий вид серверной части такой (псевдо код)
Код

void ServerProc(void)
{
    SOCKET sock = CreateSocket();
    BindScket(sock);
    ListenSocket(sock);
    
    while(bContinueRun)
    {
        SOCKET client = Accept(sock);
        if (client != SOCKET_ERROR)
            CreateThread(ClientProc, client);
    }
    ShotDownSocket(sock);
    CloseSocket(sock);
}

void ClientProc(void* param)
{
    SOCKET client = (SOCKET)param;
    ReadAndPrintText(client)
    ShutDownSocket(client);
    CloseSocket(client);
}




--------------------
user posted image
PM MAIL   Вверх
Timkin
Дата 11.10.2005, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 30.8.2005
Где: Кёльн, Германия

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



Каюсь, тот код, который я написал вначале сути проблемы не отображает...
Мне нужно, чтобы сервер находился постоянно в процессе прослушивания и аксептил ВСЕ соединения клиентов. Я поставил создание сокета и старт прослушивания в бесконечный цикл:
Код

while (true) {
  SOCKET Socket; 
  Socket = socket(AF_INET,SOCK_STREAM,0);
  if (Socket==INVALID_SOCKET)
    printf("Socket creation failed.");
  if (bind(Socket,(SOCKADDR *)(&SockAddr),sizeof(SockAddr))==SOCKET_ERROR) 
    printf("Attempt to bind failed.");
  if (listen(Socket,5)==SOCKET_ERROR)
    printf("Port listening couldn't start.\n");
  SOCKET TempSock = SOCKET_ERROR; 
  while (TempSock==SOCKET_ERROR)  
    TempSock = accept(Socket,NULL,NULL);
  Socket = TempSock;
  int RetVal = SOCKET_ERROR; 
  char String[255]; 
  RetVal = recv(Socket, String, 255, 0);
  if (RetVal!=SOCKET_ERROR) { 
    printf("Data received: %s\n",String);
    shutdown(Socket,1);
    closesocket(Socket);
  }
  if ((RetVal==0)||(RetVal==WSAECONNRESET)||(RetVal==WSAECONNABORTED)) { 
    printf("Connection closed at other end.");
    // Здесь можно ничего не писать - всё равно до этого блока прога никогда не доходит
  }
}
Но после того как данные с первого клиента получены, хост больше не может привязать сокет к порту и соответственно, начать прослушивание!!
Можно, конечно, после каждого полученного пакета делать WSACleanup() и запускать WSAStartup() заново, но тогда данные отправленные клиентами в промежутке времени между WSACleanup() и WSAStartup() теряются! Это уж не говоря о том, что теряются все строки, кроме первой с подключившегося первым клиента...
Код клиента был создан для тестирования, изменение его кода проблемы не решает...
Кто-нибудь знает, как решить проблему? КАК СКИНУТЬ ЧЁРТОВА КЛИЕНТА С ПОРТА, ПОСЛЕ ТОГО, КАК ОН ОТПРАВИЛ ВСЁ ЧТО ХОТЕЛ???

Это сообщение отредактировал(а) Timkin - 11.10.2005, 12:44
PM MAIL WWW ICQ   Вверх
Mad
Дата 11.10.2005, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

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



Цитата(Timkin @ 11.10.2005, 11:41)
Но после того как данные с первого клиента получены, хост больше не может привязать сокет к порту и соответственно, начать прослушивание!!

комманда ACCEPT возвращает НОВЫЙ сокет, а старый у тебя остаеться (тыпросто теряеш указатель на него), поэтому и порт у тебя остаеться занят

если тебе надо не паралельная обработка нескольких клиентов, а последовательная, то в моем коде просто замени CreateThread на вызов ClientProc

но обрати внимание, что в после вызова accept сервенный сокет (на который ты ставиш listen) не закрываеться, а создаеться новый клиентский сокет


--------------------
user posted image
PM MAIL   Вверх
Timkin
Дата 11.10.2005, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 30.8.2005
Где: Кёльн, Германия

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



А, дошло!:)) Спасибо!
Я в строке
Код

Socket = TempSocket;
сам же и переопределил слушающий сокет.smile
Если кому интересно, то правильный код такой:
Код

int main(int argc, char *argv[])
{
    printf("Listening port nr. 3500...\n"); 
      WSADATA WsaDat;
      if (WSAStartup(MAKEWORD(1,1),&WsaDat)!=0) 
        printf("WSA Initialization failed."); 
      char Name[255];
      gethostname(Name,255); 
      HOSTENT *HostInfo;
      HostInfo = gethostbyname(Name);
      if (HostInfo==NULL) 
        printf("Attempt to retreive computer information failed."); 
      SOCKADDR_IN SockAddr;
      SockAddr.sin_port = 3500;
      SockAddr.sin_family = AF_INET;
      SockAddr.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)HostInfo->h_addr_list[0][0]; 
      SockAddr.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)HostInfo->h_addr_list[0][1]; 
      SockAddr.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)HostInfo->h_addr_list[0][2]; 
      SockAddr.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)HostInfo->h_addr_list[0][3];
      SOCKET Socket; 
      Socket = socket(AF_INET,SOCK_STREAM,0);
      if (Socket==INVALID_SOCKET)
        printf("Socket creation failed.\n");
      if (bind(Socket,(SOCKADDR *)(&SockAddr),sizeof(SockAddr))==SOCKET_ERROR) 
        printf("Attempt to bind failed.\n");
      if (listen(Socket,5)==SOCKET_ERROR)
        printf("Port listening couldn't start.\n");
    while (true) {
      SOCKET TempSock; 
      TempSock = SOCKET_ERROR;
      printf("Waiting for a connection.\n");
      while (TempSock==SOCKET_ERROR)  
        TempSock = accept(Socket,NULL,NULL);
      printf("Connection with client established.\n");
      int RetVal = SOCKET_ERROR; 
      char String[255]; 
      RetVal = recv(TempSock, String, 255, 0);
      if (RetVal!=SOCKET_ERROR) { 
        printf("Data received: %s\n",String);
        do {
          strcpy(String,"");
          RetVal = recv(TempSock, String, 255, 0);
          if ((!RetVal)||(RetVal==SOCKET_ERROR))
            break;
          printf("Data received: %s\n",String);
        } while (RetVal!=SOCKET_ERROR);
        printf("Connection is shut down.\n");
        shutdown(TempSock,SD_SEND);
        closesocket(TempSock);
      }
    }
    printf("\nProgram terminated.\n");
    system("PAUSE");
    return EXIT_SUCCESS; 
}
- Так и читаются все данные, отправленные клиентом, и станавливаются дальнейшие соединения.smile
Всем огромное спасибо!!!

Это сообщение отредактировал(а) Timkin - 11.10.2005, 15:33
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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