На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
    > Сервсер на сокетах , как делать accept?
      Вообщем пытаюсь создать нормальный сервер ка сокетах.
      Проблема в том, что не могу понять как сделать accept (прием)
      при конекте.
      То есть, создаеться сокет, вешаеться на порт, слушает обращения, а дальше что?
      Как правильно исполльзовать accept? Как обработать обращение на прослушиваемый порт?

      ExpandedWrap disabled
         
        WORD wVersionRequested;
        WSADATA wsaData;
         
        wVersionRequested = MAKEWORD( 2, 2 );
         
         
        // открываем сокет
           if (WSAStartup( wVersionRequested, &wsaData ))
           {
                   MessageBox (NULL,"Ошибка инициализации dll",0,0);        
           }
         
         
        // создаем сокет
           SOCKET mysocket;          
           mysocket = socket(PF_INET, SOCK_STREAM, 0 );
         
        // привязываем сокет к порту
         
                SOCKADDR_IN socketaddr;
                socketaddr.sin_family = AF_INET;
                socketaddr.sin_addr.s_addr  = INADDR_ANY;
                socketaddr.sin_port = htons (17700);
         
                if (bind(mysocket,(LPSOCKADDR) &socketaddr,sizeof(socketaddr)) == SOCKET_ERROR)
                {
                        MessageBox (NULL,"Жопа",0,0);
                        exit(1);
                }
                else MessageBox (NULL,"Привязываем сокет к 17700 порту",0,0);
         
                if(listen(mysocket , 1) == SOCKET_ERROR )
                {
                  MessageBox(NULL, "listen Error", "Error", MB_OK);
                  return;
                }
         
                sockaddr new_sockaddr;
                int lenz_sockaddr;
            
                SOCKET newsocket = accept ( mysocket,  &new_sockaddr, &lenz_sockaddr);
                MessageBox (NULL, "Пришол вызов", 0,0);
         
        closesocket(mysocket);
         
        // закрываем сокет  
           if (WSACleanup() == 0) MessageBox (NULL,"Закрытие сокета удачно",0,0);


      Такой код просто завершаеться, тоесть сокет создаться, забиндился и закрылся.
      Как поставить его в режим ожидания?
        В поток его :wall:
          Гм. Если чесно я не умею пока создавать потоки. Но код исправил.
          Между прочим от нефиг делать зашол на msdn.microsoft.com и нашол там полностью
          рабочий код. Так что всем рекомендую.

          http://msdn.microsoft.com/library/default....server_code.asp

          ExpandedWrap disabled
             
            #include <stdio.h>
            #include "winsock2.h"
             
            void main() {
             
                // Initialize Winsock.
                WSADATA wsaData;
                int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
                if ( iResult != NO_ERROR )
                    printf("Error at WSAStartup()\n");
             
                // Create a socket.
                SOCKET m_socket;
                m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
             
                if ( m_socket == INVALID_SOCKET ) {
                    printf( "Error at socket(): %ld\n", WSAGetLastError() );
                    WSACleanup();
                    return;
                }
             
                // Bind the socket.
                sockaddr_in service;
             
                service.sin_family = AF_INET;
                service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
                service.sin_port = htons( 27015 );
             
                if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
                    printf( "bind() failed.\n" );
                    closesocket(m_socket);
                    return;
                }
                
                // Listen on the socket.
                if ( listen( m_socket, 1 ) == SOCKET_ERROR )
                    printf( "Error listening on socket.\n");
             
                // Accept connections.
                SOCKET AcceptSocket;
             
                printf( "Waiting for a client to connect...\n" );
                while (1) {
                    AcceptSocket = SOCKET_ERROR;
                    while ( AcceptSocket == SOCKET_ERROR ) {
                        AcceptSocket = accept( m_socket, NULL, NULL );
                    }
                    printf( "Client Connected.\n");
                    m_socket = AcceptSocket;
                    break;
                }
                
                // Send and receive data.
                int bytesSent;
                int bytesRecv = SOCKET_ERROR;
                char sendbuf[32] = "Server: Sending Data.";
                char recvbuf[32] = "";
                
                bytesRecv = recv( m_socket, recvbuf, 32, 0 );
                printf( "Bytes Recv: %ld\n", bytesRecv );
                
                bytesSent = send( m_socket, sendbuf, strlen(sendbuf), 0 );
                printf( "Bytes Sent: %ld\n", bytesSent );
             
                return;
            }
            Цитата Duke Nuken, 27.09.04, 16:45
            AcceptSocket = SOCKET_ERROR;
            while ( AcceptSocket == SOCKET_ERROR ) {
            AcceptSocket = accept( m_socket, NULL, NULL );
            }


            за одно вот это автору надо оторвать руки...
            чему они учат??

            этож какая загрузка проца идет..

            поищи на форуме по поводу WSAEventSelect.. сильная вещь и решает все проблемы..
            я выкладывал готовуб потоковую функцию.. там в ней все есть..
              Так. Разобрался с потоками, согласен кривой метод accept в цикле крутить,
              но в потоке терпимо и не жрет почти ничего. Я смотрел, код в ожидании еъст
              меньше одного процента.

              Нашол вот такой вот код на майкрософте с использованием WSAWaitForMultipleEvents
              ExpandedWrap disabled
                 
                  //-----------------------------------------
                  // Declare and initialize variables
                  WSABUF DataBuf;
                  char buffer[DATA_BUFSIZE];
                  DWORD EventTotal = 0,
                    RecvBytes = 0,
                    Flags = 0,
                    BytesTransferred = 0,
                    CallBack = 0;
                  WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
                  WSAOVERLAPPED AcceptOverlapped;
                  SOCKET ListenSocket, AcceptSocket;
                 
                  //-----------------------------------------
                  // Initialize Winsock
                  WSADATA wsaData;
                  WSAStartup(MAKEWORD(2,2), &wsaData);
                 
                  //-----------------------------------------
                  // Create a listening socket bound to a local
                  // IP address and the port specified
                  ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                 
                  sockaddr_in service;
                  service.sin_family = AF_INET;
                  service.sin_port = htons(17700);
                 
                  service.sin_addr.s_addr = htonl(INADDR_ANY);
                 
                  //-----------------------------------------
                  // Bind the listening socket to the local IP address
                  // and port number
                  bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
                 
                  //-----------------------------------------
                  // Set the socket to listen for incoming
                  // connection requests
                  listen(ListenSocket, 1);
                  //printf("Listening...\n");
                 
                  //-----------------------------------------
                  // Accept and incoming connection request
                  AcceptSocket = accept(ListenSocket, NULL, NULL);
                 
                  //-----------------------------------------
                  // Create an event handle and setup an overlapped structure.
                  EventArray[EventTotal] = WSACreateEvent();
                  ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
                  AcceptOverlapped.hEvent = EventArray[EventTotal];
                  DataBuf.len = DATA_BUFSIZE;
                  DataBuf.buf = buffer;
                  EventTotal++;
                 
                  //-----------------------------------------
                  // Call WSARecv to receive data into DataBuf on
                  // the accepted socket in overlapped I/O mode
                  if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
                  {
                    if (WSAGetLastError() != WSA_IO_PENDING)
                      printf("Error occurred at WSARecv()\n");
                  }
                 
                  //-----------------------------------------
                  // Process overlapped receives on the socket
                  while (1) {
                    DWORD Index;
                 
                    //-----------------------------------------
                    // Wait for the overlapped I/O call to complete
                    Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
                 
                    //-----------------------------------------
                    // Reset the signaled event
                    WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
                 
                    //-----------------------------------------
                    // Determine the status of the overlapped event
                    WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);
                 
                    //-----------------------------------------
                    // If the connection has been closed, close the accepted socket
                    if (BytesTransferred == 0) {
                      printf("Closing Socket %d\n", AcceptSocket);
                      closesocket(AcceptSocket);
                      WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
                      return;
                    }
                 
                    //-----------------------------------------
                    // If data has been received, echo the received data
                    // from DataBuf back to the client
                    if (WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
                      printf("WSASend() is busted\n");
                 
                    //-----------------------------------------    
                    // Reset the changed flags and overlapped structure
                    Flags = 0;
                    ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
                 
                    AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
                 
                    //-----------------------------------------
                    // Reset the data buffer
                    DataBuf.len = DATA_BUFSIZE;
                    DataBuf.buf = buffer;
                  }


              Ну тут чтото странное... Он зависает на аксепте...
              ExpandedWrap disabled
                  AcceptSocket = accept(ListenSocket, NULL, NULL);

              Я тестироывал обращаясь из IE на указаный порт, получал в ответ
              в броузаер чтото вроде
              Цитата

              GET / HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */* Accept-Language: ru Cookie: phpbb2mysql_data=a%3A2%3A%7Bs%3A11%3A%22autologinid%22%3Bs%3A32%3A%222063c1608d6e0baf80249c42e2be5804%22%3Bs%3A6%3A%22userid%22%3Bi%3A2%3B%7D; avtforum_data=a%3A0%3A%7B%7D; b=b User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.1.4322) Host: 192.168.1.19:17700 Connection: close МММММММММММММММММММММММММММММММММММММММММММММММММММММММММММ...

              и при дебаге скрипт оставался на строке аксепта. :blink:

              Вообщем хотелбы для себя понять теорию.
              Вот создал я сокет. Забиндил его на порт. Слушаю.
              Потом, судя по коду выполняеться аксепт.

              Потом вызываеться функция WSACreateEvent(); - создаеться событие
              а дальше идет какаято ерунда смысла которой я не могу понять...
              Поясните, плз.
              Сообщение отредактировано: Duke Nuken -
                ТЫ немного не то нашел! :)
                Просто ты нашел как работать с асинхронным вводом\выводом на сокетах.
                На accept зависает так как ожидает соединения, когда какой-нибудь клиент сделает connect к данному серверу в дебаге ты пойдешь дальше...

                И все же лучше использовать WSAEventSelect! ;)

                Добавлено
                А происходит в твоем коде вот что:
                После того как принимаем соединение, мы что-то там отправляем,
                в данном случае наш обьект событие находится в занятом состоянии...
                После этого мы вызываем WSAWaitForMultipleEvents в котором ожидаем, когда закончится операция ввода\вывода на сокете, когда операция заканчивается, обьект событие переходит в свободное состояние. С помощью WSAGetOverlappedResult мы проверяем на сколько корректно прошла I\O операция.
                Ели прошла с ошибкой, то закрываем сокет и и выходим, иначе отсылаем ккие-то там данные и читаем начиная с WSAWaitForMultipleEvents! :)
                  to ViGOur

                  Слушай, поясни, будь добр, что вообще дает механизм с использованием
                  этих WSAEventSelect?
                  Ну вот когда делаеш аксепт, то там создаеться новый сокет.
                  С ним работаеш (принимаеш, отправляеш данные), а потом просто закрываеш этот
                  созданый сокет.

                  ТОесть схема такая.
                  ExpandedWrap disabled
                    socket()
                    bind()
                    listen()
                    цикл accept()
                      {
                         recv с новым сокетом
                         send с новым сокето
                         closesocket с новым сокетом
                      }


                  А как получаеться схема с WSAEventSelect?
                  Сообщение отредактировано: Duke Nuken -
                    вот откуда-то выдрал.. старая прога... или тест.. не помню.. но вроде работает и для понимания достаточно..

                    ExpandedWrap disabled
                       
                      DWORD _stdcall  ReadThread(LPVOID pParam)
                      {
                          SOCKET*pSock=(SOCKET*)pParam;
                          WSAEVENT  wsaEvent[2];
                       
                        DWORD err=1,index;
                        WSANETWORKEVENTS  NetworkEvents;
                        DWORD EventIndex,dwErr,dwFlag=MSG_PARTIAL,dwRet,dwNum;
                        char buf[BLOCK_LENGTH+4];
                        WSABUF wsabuf;
                        wsabuf.len=300;
                        wsabuf.buf=new char[wsabuf.len];
                       
                        wsaEvent[0]=StopEvent;
                        wsaEvent[1]=WSACreateEvent();
                        WSAEventSelect(*pSock,wsaEvent[1],FD_READ|FD_CLOSE);
                       
                        while(err)
                        {
                          EventIndex=WSAWaitForMultipleEvents(2,wsaEvent,FALSE,WSA_INFINITE,FALSE);
                          index=EventIndex-WSA_WAIT_EVENT_0;
                          if(index==0)
                            break;
                          WSAEnumNetworkEvents(*pSock,wsaEvent[1],&NetworkEvents);
                       
                          if(NetworkEvents.lNetworkEvents&FD_READ)
                          {
                            if(NetworkEvents.iErrorCode[FD_READ_BIT]==0)
                            {
                              dwRet=WSARecv(*pSock,&wsabuf,1,&dwNum,&dwFlag,NULL,NULL/*CompletionROUTINE*/);
                              dwRet=WSARecv(*pSock,&wsabuf,1,&dwNum,&dwFlag,NULL,NULL/*CompletionROUTINE*/);
                              dwErr=WSAGetLastError();
                                    printf("%s\n",wsabuf.buf);
                       
                      //               recv(*pSock,buf,BLOCK_LENGTH,0);
                      //               printf("%s\n",buf);
                                  }
                          }
                       
                          if(NetworkEvents.lNetworkEvents&FD_CLOSE)
                          {
                            if(NetworkEvents.iErrorCode[FD_CLOSE_BIT]==0)
                            {
                              WSACloseEvent(wsaEvent[1]);
                              closesocket(*pSock);
                                      delete pSock;
                              return 0;
                            }
                          }
                        }
                          closesocket(*pSock);
                          delete pSock;
                          SetEvent(hStop[1]);
                          return 0;
                      }
                       
                       
                      DWORD _stdcall EventSelect(LPVOID pParam)
                      {
                        SOCKET  Listen,sock;
                        SOCKADDR_IN addr;
                        WSAEVENT  wsaEvent[3];
                       
                        DWORD err=1,index,tmp;
                        WSANETWORKEVENTS  NetworkEvents;
                        DWORD EventIndex;
                        
                        Listen=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
                        if(Listen==SOCKET_ERROR)
                        {
                          return 0;
                        }
                          
                        addr.sin_family=AF_INET;
                        addr.sin_addr.s_addr=GetCurrentIP();
                        addr.sin_port=htons(7007);
                        if(bind(Listen,(PSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
                        {
                          closesocket(Listen);
                          return 0;
                        }
                       
                        wsaEvent[0]=StopEvent;
                        wsaEvent[1]=WSACreateEvent();
                        wsaEvent[2]=WSA_INVALID_EVENT;
                        WSAEventSelect(Listen,wsaEvent[1],FD_ACCEPT|FD_CLOSE);
                        listen(Listen,5);
                       
                        while(err)
                        {
                          EventIndex=WSAWaitForMultipleEvents(2,wsaEvent,FALSE,WSA_INFINITE,FALSE);
                          index=EventIndex-WSA_WAIT_EVENT_0;
                          if(index==0)
                            break;
                            WSAEnumNetworkEvents(Listen,wsaEvent[1],&NetworkEvents);
                              tmp=WSAGetLastError();
                          if(NetworkEvents.lNetworkEvents&FD_ACCEPT)
                          {
                            if(NetworkEvents.iErrorCode[FD_ACCEPT_BIT]==0)
                            {
                              SOCKET*pSock=new SOCKET;
                                      *pSock=accept(Listen,NULL,NULL);
                                      ResetEvent(hStop[1]);
                                      printf("Starting clinet\n");
                              CloseHandle(CreateThread(NULL,0,ReadThread,(LPVOID)pSock,0,NULL));
                            }
                          }
                       
                          if(NetworkEvents.lNetworkEvents&FD_CLOSE)
                          {
                      //        if(NetworkEvents.iErrorCode[FD_CLOSE_BIT]==0)
                      //      {
                              WSACloseEvent(wsaEvent);
                              closesocket(Listen);
                                    SetEvent(hStop);
                              return 1;
                      //      }
                          }
                        }
                        printf("Terminated...\n");
                        WSACloseEvent(wsaEvent[1]);
                        closesocket(Listen);
                        SetEvent(hStop[0]);
                        return 0;
                      }


                    Добавлено
                    1. а механизм дает возможность более гибкой работы с вводом\выодом в сокеты..
                    поток-оьработччик работает только когда ему есть чем заниматься..
                    принимать подключения, или читать даные..
                    все остальное время он не мешает работе других потоков..

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

                      Люди скажите мне вот что:

                      В схема с Eventam'и такая?

                      ExpandedWrap disabled
                        socket()
                        bind()
                        listen()
                         
                        цикл
                        {  
                            WSAWaitForMultipleEvents()
                            
                            WSAEnumNetworkEvents()
                           ... и тут разбор того что за событие пришло...  
                        }


                      1) Как я понял тут accept вообще не используеться. Да?
                      2) Если функция описана так
                      ExpandedWrap disabled
                        WSAWaitForMultipleEvents(2, &NewEvent, FALSE, WSA_INFINITE, FALSE);

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

                        Проблема. После того как производиться привязка события к порту функцией WSAEventSelect()
                        функция recv() перестает коректно работать. Дело в том, что когда просто слушать порт и
                        после конекта вызывать recv(), то она замерает в ожидании пока не получит какие-либо данные.
                        А после того как на слушающий сокет вешаеться событие и не успели отправить данные, то recv()
                        завершаеться сразуже с результатом -1.
                        Почему так происходит?



                        ExpandedWrap disabled
                          WORD wVersionRequested;
                          WSADATA wsaData;
                           
                          wVersionRequested = MAKEWORD( 2, 2 );
                           
                          // открываем сокет
                             if (WSAStartup( wVersionRequested, &wsaData ))
                             {
                                     MessageBox (NULL,"Ошибка инициализации dll",0,0);        
                             }
                           
                           
                          // создаем сокет
                             SOCKET ListenSocket;          
                             ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                           
                          // привязываем сокет к порту
                           
                                  SOCKADDR_IN socketaddr;
                                  socketaddr.sin_family = AF_INET;
                                  socketaddr.sin_addr.s_addr  = htonl(INADDR_ANY); //inet_addr("192.168.1.19");;
                                  socketaddr.sin_port = htons (17700);
                           
                                  if (bind(ListenSocket,(SOCKADDR*) &socketaddr,sizeof(socketaddr)) == SOCKET_ERROR)
                                  {
                                          MessageBox (NULL,"Жопа",0,0);
                                          exit(1);
                                  }
                                  else MessageBox (NULL,"Привязываем сокет к 17700 порту",0,0);
                           
                                  if(listen(ListenSocket , 1) == SOCKET_ERROR )
                                  {
                                    MessageBox(NULL, "listen Error", "Error", MB_OK);
                                    return 0;
                                  }
                           
                          WSAEVENT NewEvent;
                           
                          NewEvent = WSACreateEvent();
                          WSAEventSelect ( ListenSocket,  NewEvent, FD_ACCEPT | FD_CLOSE);
                           
                           
                          SOCKET AcceptSocket; //сокет на приемом соеденения
                          char cstr[255]; // буфер приема
                           
                           
                          //-------------------------
                          // Wait for network events on all sockets
                          int Index = WSAWaitForMultipleEvents(1, &NewEvent, FALSE, WSA_INFINITE, FALSE);
                           
                          WSAEnumNetworkEvents(ListenSocket, EventArray, &NetworkEvents);
                           
                           
                          if( ConnectEvent.lNetworkEvents & FD_ACCEPT )
                          {
                              AcceptSocket = WSAAccept(ListenSocket, &saClient, &iClientSize, NULL, NULL);
                           
                              int recvd = recv (AcceptSocket, cstr, sizeof(cstr), 0); // получаем данные с сокета
                              MessageBox (NULL, cstr, "Переданые данные",0);
                           
                              closesocket(AcceptSocket);
                          }
                           
                          .......



                        Вот в строке int recvd = recv (AcceptSocket, cstr, sizeof(cstr), 0);
                        происходит глюк, потому что функция перестает ожидать что ей чтото прислали
                        и если есть данные она их отображает, если их нет выдает ошибку.
                        Почему не происходит ожидание?

                        Есть другой вариант, слушать события для новосозданого сокета (AcceptSocket),
                        но чтото странно работают эти события. Когда я ожидаю события FD_WRITE на AcceptSocket,
                        то оно тутже наступает. Почему спрашиваеться???

                        ExpandedWrap disabled
                           
                          int Index = WSAWaitForMultipleEvents(1, &NewEvent, FALSE, WSA_INFINITE, FALSE);
                           
                           
                          SOCKET AcceptSocket; //сокет на приемом соеденения
                          char cstr[255]; // буфер приема
                           
                          WSAEnumNetworkEvents(ListenSocket, EventArray, &NetworkEvents);
                           
                           
                          WSAEVENT NewEvent2;
                          WSANETWORKEVENTS NetworkEvents2;
                           
                           
                          if( ConnectEvent.lNetworkEvents & FD_ACCEPT )
                          {
                              AcceptSocket = accept( ListenSocket, NULL, NULL );
                           
                              NewEvent2 = WSACreateEvent();
                           
                              WSAEventSelect ( AcceptSocket,  NewEvent2, FD_WRITE);
                           
                              Index = WSAWaitForMultipleEvents(1, &NewEvent2, FALSE, WSA_INFINITE, FALSE);
                           
                          //  MessageBox (NULL, "Ожидаем передачу данных", "Сокеты",0);
                           
                              int recvd = recv (AcceptSocket, cstr, sizeof(cstr), 0); // получаем данные с сокета
                              MessageBox (NULL, cstr, "Переданые данные",0);
                        Сообщение отредактировано: Uncle_Bob -
                          Цитата Muran, 27.09.04, 18:01
                          этож какая загрузка проца идет..

                          Нулевая. Сокеты блокирующие => accept блокируется до подключения нового клиента.
                            Вообщем вопрос. Как следует поступать при такой схеме:

                            Есть сервер и клиент.
                            1 этап - сервер) Я создаю сокет и вешаю на него событие ACCEPT.
                            начинаю ожидать его функцией WSAWaitForMultipleEvents()
                            2 этап - клиент) Соеденяюсь с сервером. connect() и тутже отправляю данные send()
                            3 этап - сервер) Обрабатываю событие WSAEnumNetworkEvents() и пытаюсь
                            сделать accept на новый сокет.
                            4 этап - сервер) Пытаюсь забрать присланые на сервер данные recv()

                            Бред происходит в том, что если клиент сразу же после конекта отсылает данные
                            до того как на сервере производиться accept нового соеденения, то данные отсылаються
                            в никуда. ТОесть нужно успеть сделать accept на сервере. Ну ставить всякие Sleep на
                            клиенте этоже не дело.
                            Я вот не пойму никак если секет создаеться командой socket, то он изначально какой?
                            Синхронный или асинхронный? Я точно знаю что он блокируемый. Но вот если использовать
                            функцию WSAAsyncSelect() то сокет становиться не блокируемым на сервере. А если на клиенте
                            блокируемый? То гда что? Ни кто из них не измениться? Ну тоесть не станит из блокируемого
                            в не блокируемый и на оборот.
                              Вообщем, провозился с этой ассинхронностью4 дня. Таки сделал.
                              И знаете что я думаю? Что это ПОЛНАЯ чушь. Она ничерта не дает ни в
                              скорости, ни в надежности, ни в ресурсоемкости...

                              Если писать сервак который обрабатывает много клиентов, то это делаеться просто
                              обычными блокируемыми сокетами. Один из них слушает в цикле и как только производиться
                              конект создает новый сокет функцией accept и передает его обработку в поток, а сам
                              возвращаеться в ожидание.

                              Вот 100% рабочий код на неограниченое кол-во подключений.

                              ExpandedWrap disabled
                                 
                                DWORD WINAPI WorkOnSocket(LPVOID lpParam);
                                 
                                UINT Server_Run (LPVOID pParam)
                                {
                                 
                                WORD wVersionRequested;
                                WSADATA wsaData;
                                 
                                 
                                wVersionRequested = MAKEWORD( 2, 2 );
                                 
                                 
                                // открываем сокет
                                   if (WSAStartup( wVersionRequested, &wsaData ))
                                   {
                                           MessageBox (NULL,"Ошибка инициализации dll",0,0);        
                                   }
                                 
                                 
                                // создаем сокет
                                   SOCKET mysocket;          
                                   mysocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                                 
                                // привязываем сокет к порту
                                 
                                        SOCKADDR_IN socketaddr;
                                        socketaddr.sin_family = AF_INET;
                                        socketaddr.sin_addr.s_addr  = htonl(INADDR_ANY); //inet_addr("192.168.1.19");;
                                        socketaddr.sin_port = htons (17700);
                                 
                                        if (bind(mysocket,(SOCKADDR*) &socketaddr,sizeof(socketaddr)) == SOCKET_ERROR)
                                        {
                                                MessageBox (NULL,"Жопа",0,0);
                                                exit(1);
                                        }
                                        else MessageBox (NULL,"Привязываем сокет к 17700 порту",0,0);
                                 
                                        if(listen(mysocket , 1) == SOCKET_ERROR )
                                        {
                                          MessageBox(NULL, "listen Error", "Error", MB_OK);
                                          return 0;
                                        }
                                 
                                 
                                 
                                  //----------------------
                                  // Create a SOCKET for accepting incoming requests.
                                  SOCKET AcceptSocket;
                                 
                                  //----------------------
                                  // Accept the connection.
                                  while(1) {
                                    AcceptSocket = SOCKET_ERROR;
                                        while( AcceptSocket == SOCKET_ERROR )
                                        {
                                                    /* вот в этом цикле слушаеться сокет mysocket и как только
                                                     производиться подключение, создаеться AcceptSocket и передаеться
                                                     в поток. Сам mysocket возвращаеться в режим ожидания. */
                                          AcceptSocket = accept( mysocket, NULL, NULL );
                                        }
                                        unsigned long id;
                                        CreateThread ( NULL, 0, WorkOnSocket, (LPVOID) AcceptSocket, 0, &id );
                                 
                                   // break;
                                  }
                                 
                                  
                                closesocket(mysocket);
                                 
                                // закрываем сокет  
                                   if (WSACleanup() == 0) MessageBox (NULL,"Закрытие сокета удачно",0,0);
                                 
                                   return 1;
                                }
                                 
                                 
                                 
                                DWORD WINAPI WorkOnSocket(LPVOID lpParam)
                                {
                                    char cstr[100];
                                 
                                    SOCKET client = (SOCKET) lpParam;
                                 
                                    int recvd = recv (client, cstr, sizeof(cstr), 0); //client? допустим, мы на сервере!
                                //  MessageBox (NULL, cstr, "Полученые данные",0);
                                 
                                    
                                    char send_cstr[] = "Data get OK. Thanks you.";
                                    
                                    int sent = send (client, send_cstr, sizeof(send_cstr), 0);
                                 
                                    closesocket(client);
                                    
                                    return 1;
                                }
                                Duke Nuken, по поводу последнего исходника... (хотел отослать приватное сообщение, но не работает)

                                ExpandedWrap disabled
                                   
                                      // Accept the connection.
                                      while(1)
                                      {
                                          AcceptSocket = SOCKET_ERROR;
                                          while( AcceptSocket == SOCKET_ERROR )
                                          {
                                              /* вот в этом цикле слушаеться сокет mysocket и как только
                                               производиться подключение, создается AcceptSocket и передаеться
                                               в поток. Сам mysocket возвращается в режим ожидания. */
                                              AcceptSocket = accept( mysocket, NULL, NULL );
                                          }
                                          unsigned long id;
                                          CreateThread ( NULL, 0, WorkOnSocket, (LPVOID) AcceptSocket, 0, &id );
                                          // break;
                                      }

                                по коду:
                                а если подключение не производится?
                                тогда сразу идёт создавать поток?!

                                глобально:
                                после обнаружение подключения клиентом программа создаёт отдельный поток, к-й получает поступившую на сокет информацию, так?
                                он работает с копией сокета или самим экземпляром сокета?
                                  Гм. Это уже устаревший код.
                                  Я был таки не прав, сервак точно нужно на аснхронных сокетах писать.
                                  Там все сокеты обрабатываються в одном потоке.

                                  Чтоже до устаревшего кода, то если ты внимательно читал, то это БЛОКИРУЕМЫЕ сокеты.
                                  И если ты все правильно сделал, то на строке
                                  ExpandedWrap disabled
                                    AcceptSocket = accept( mysocket, NULL, NULL );

                                  поток заморозиться, ожидая accept.
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0924 ]   [ 16 queries used ]   [ Generated: 26.12.24, 23:12 GMT ]