На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
    > nonblocking sockets C (си) , connect () failed: no error
      Цитата sign63 @
      не открывается соединение.

      char servIP[] = "10.42.43.1";
      Этот IP - где он находится? В вашей локальной сети?
      И после connect() обязательно поставить WSAGetLastError() - без кода ошибки при соединении - узнать истинную причину невозможно.
      Это закон сетевого программирования - WSAGetLastError() после каждой сетевой функции.
      Например:
      r = recv(...);
      if (r == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
        Слабо поменять местами?
        Вот так:
        ExpandedWrap disabled
          {
              /* Establish the connection to the echo server */
              if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
                  rc = select(sock, NULL, &writefds, NULL, &tv);
                   if((rc == 1) && (FD_ISSET(sock, &writefds)))
                    {printf("УРА!");}
                   else
          //        DieWithError("connect() failed");
              }
          Цитата Oleg2004 @
          Цитата sign63 @
          не открывается соединение.

          char servIP[] = "10.42.43.1";
          Этот IP - где он находится? В вашей локальной сети?
          И после connect() обязательно поставить WSAGetLastError() - без кода ошибки при соединении - узнать истинную причину невозможно.
          Это закон сетевого программирования - WSAGetLastError() после каждой сетевой функции.
          Например:
          r = recv(...);
          if (r == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)

          это ip хоста внутренней сети для доступа winxp из виртуалки к серверу на убунте (хосту)
          Добавлено
          Цитата Паровоз @
          Слабо поменять местами?
          Вот так:
          ExpandedWrap disabled
            {
                /* Establish the connection to the echo server */
                if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
                    rc = select(sock, NULL, &writefds, NULL, &tv);
                     if((rc == 1) && (FD_ISSET(sock, &writefds)))
                      {printf("УРА!");}
                     else
            //        DieWithError("connect() failed");
                }

          я сначала не заметил вторую страницу, решил проблему - сделал также как ты написал.
          Сообщение отредактировано: sign63 -
            кто здесь, кто здесь??? :ph34r:
            вот почему
            Цитата
            With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK.

            тоесть как только сокет стал неблокирующим, в любом случае connect обязан возвращать SOCKET_ERROR (!). Это значит, что процесс коннекта начался успешно.
            Короче, упрощаемся немного. Подобно эхо серверу - коннектимся на яндекс, на 80-й порт, шлем лабудень, получаем в ответ 400 и наслаждаемся. Пардон, пишу левой ногой без телячьих нежностей ввиду отсутсвия времени. Чуть покорячу приведенный код - увеличу буфер и напишу как нада коннектиться. Не пинать типа "а чё ты не проверил что коннект вернул сокет_еррор" и т.п. Все детали - мсдн.
            ExpandedWrap disabled
              #include <stdio.h>      /* for printf(), fprintf() */
              #include <winsock2.h>    /* for socket(),... */
              #include <stdlib.h>     /* for exit() */
              #include <time.h>
              #include <sys/types.h>
               
              #define RCVBUFSIZE 3200   /* Size of receive buffer */
               
              void DieWithError(char *errorMessage){
                  perror(errorMessage);
                  exit(0);
              };  /* Error handling function */
               
              void main(int argc, char *argv[])
              {
                  int sock, rc;                        /* Socket descriptor */
                  struct sockaddr_in echoServAddr; /* Echo server address */
                  unsigned short echoServPort;     /* Echo server port */
                  //char *servIP;                    /* Server IP address (dotted quad) */
                  char servIP[] = "93.158.134.8";
                  char echoString[]= "identifier=1z2y3z \r\n\r\n";
                  char echoBuffer[RCVBUFSIZE];     /* Buffer for echo string */
                  int echoStringLen;               /* Length of string to echo */
                  int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv() and total bytes read */
                  WSADATA wsaData;                 /* Structure for WinSock setup communication */
                  unsigned long nonblocking = 1;
                  fd_set writefds, readfds;
                  struct timeval tv;
                  tv.tv_sec = 5;
                  tv.tv_usec = 500000;
                  //servIP =  argv[1];             /* First arg: server IP address (dotted quad) */
                  echoServPort = 80; //atoi(8088);  //atoi(argv[2]);  /* Use given port, if any */
               
                  if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */
                  {
                      fprintf(stderr, "WSAStartup() failed");
                      exit(1);
                  }
               
                  /* Create a reliable, stream socket using TCP */
                  if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) < 0)
                      DieWithError("socket() failed");
                
               
                  /* Set the socket to nonblocking */
                  if (ioctlsocket(sock, FIONBIO, &nonblocking) != 0)
                      DieWithError("ioctlsocket() failed");
               
                  /* Construct the server address structure */
                  memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
                  echoServAddr.sin_family      = AF_INET;             /* Internet address family */
                  echoServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
                  echoServAddr.sin_port        = htons(echoServPort); /* Server port */
               
                  connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr));
               
                  FD_ZERO(&writefds);
                  FD_SET(sock, &writefds);
                  rc = select(sock, NULL, &writefds, NULL, &tv);
               
                  if((rc == 1) && (FD_ISSET(sock, &writefds))) {
                      printf("connect success\n");
                  } else {
                      printf("connect error\n");
                  return;
                  }
               
                  send(sock, "1234", 4, 0);// шлем лабудень
               
                  FD_ZERO(&readfds);
                  FD_SET(sock, &readfds);
                  rc = select(sock, &readfds, NULL, NULL, &tv);
               
                  printf("read\n");
               
               
                  if((rc == 1) && (FD_ISSET(sock, &readfds))) { // получаем ответ и выводим на экран
                      bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0);
                      printf("received %d bytes\n", bytesRcvd);
                      printf("%s\n", echoBuffer);
                      } else {
                  printf("read error\n");
                  return;
                  }
               
                  WSACleanup();  // Cleanup Winsock
              }


            такая вот фигня..
            Собираем этот кайф прямо строчным компилятором
            Цитата
            G:\user\lim\temp11>cl fib.cpp Ws2_32.lib
            Microsoft ® 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
            Copyright © Microsoft Corp 1984-1998. All rights reserved.

            fib.cpp
            Microsoft ® Incremental Linker Version 6.00.8168
            Copyright © Microsoft Corp 1992-1998. All rights reserved.

            /out:fib.exe
            fib.obj
            Ws2_32.lib


            результат
            Цитата
            G:\user\lim\temp11>fib.exe
            connect success
            read
            received 166 bytes
            <html>
            <head><title>400 Bad Request</title></head>
            <body bgcolor="white">
            <center><h1>400 Bad Request</h1></center>
            <hr><center>nginx</center>
            </body>
            </html>
              Цитата nemez @

              Чтож ты раньше не пришел <_<
              а мсдн я смотрел, да. жаль там примеры на cpp
              Сообщение отредактировано: sign63 -
                Цитата
                я сначала не заметил вторую страницу, решил проблему - сделал также как ты написал.

                Я тебе с утра еще об этом написал. Ночью спать надо ;)
                  Цитата nemez @
                  результат
                  Цитата
                  G:\user\lim\temp11>fib.exe
                  connect success
                  read
                  received 166 bytes
                  <html>
                  <head><title>400 Bad Request</title></head>
                  <body bgcolor="white">
                  <center><h1>400 Bad Request</h1></center>
                  <hr><center>nginx</center>
                  </body>
                  </html>

                  а результат приходит только когда сервер разорвет соединение :(
                  Сообщение отредактировано: sign63 -
                    ответ неправильный. Щас напишу как оно есть на самом деле.

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

                    argp - это дворд

                    Винда:
                    ioctl( Socket, FIONREAD, &argp );
                    Линукс:
                    ioctlsocket( Socket, FIONREAD, &argp );

                    Далее:
                    if ( argp > 0 ) {
                    bytesLen = recv(Socket, Buffer, argp, 0 );
                    // ....... и далее что нужно
                    }

                    if ( argp == 0) {
                    close(asCallData[wChannel].sSrcSocket);
                    }

                    собственно так. Тоесть, если в сокете ноль байт - это значит что сообщение разорвано. В противном случае - там есть данные, их надо оттуда выгрести и обработать
                      @nemez откуда ты так хорошо знаешь winsock для Си? Рыл инет, колво литературы по этому предмету - стремится к нулю. А та что действительно хорошая - на английском, благо английский это не проблема

                      Добавлено
                      Цитата nemez @
                      Винда:
                      ioctl( Socket, FIONREAD, &argp );
                      Линукс:
                      ioctlsocket( Socket, FIONREAD, &argp );

                      только наоборот
                      Линукс:
                      ioctl( Socket, FIONREAD, &argp );
                      Мастдай:
                      ioctlsocket( Socket, FIONREAD, &argp );
                      Сообщение отредактировано: sign63 -
                        еще вспомним
                        fcntl(sockfd, F_SETFL, O_NONBLOCK);
                        вариантов масса.

                        Цитата
                        собственно так. Тоесть, если в сокете ноль байт - это значит что сообщение разорвано. В противном случае - там есть данные, их надо оттуда выгрести и обработать

                        Еще забыл про -1 в неблокирующих. Значит, что ничего не пришло.
                        ExpandedWrap disabled
                              fcntl(sockfd, F_SETFL, O_NONBLOCK);
                              buffer.i = 0;
                              while(! stop)
                              {
                                   nbytes = recv(sockfd, data, sizeof(data), 0);
                              switch(nbytes)
                              {
                                  case -1:
                                  case  0:
                                    if(errno != EAGAIN)
                                    {
                                        sprintf(msg, "READ: server: closed connection");
                                             if (close(sockfd))
                                           perror("CLOSE: ");
                                        }
                                    nanosleep(&req, NULL);
                                    break;
                                  default:
                                              sprintf(msg, "socket: %d Bytes, err = %d\n", nbytes); // process data
                          .....

                        Примерно таким куском я обычно пользуюсь
                        Сообщение отредактировано: Паровоз -
                          Цитата nemez @
                          ответ неправильный. Щас напишу как оно есть на самом деле.

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

                          argp - это дворд

                          ioctlsocket( Socket, FIONREAD, &argp );

                          Далее:
                          if ( argp > 0 ) {
                          bytesLen = recv(Socket, Buffer, argp, 0 );
                          // ....... и далее что нужно
                          }

                          if ( argp == 0) {
                          close(asCallData[wChannel].sSrcSocket);
                          }

                          собственно так. Тоесть, если в сокете ноль байт - это значит что сообщение разорвано. В противном случае - там есть данные, их надо оттуда выгрести и обработать

                          так отосланные данные всё равно показывается в клиенте после того, когда сервер рвет соединение. и прога на этом естессн выходит
                          а когда сервер не рвет соединение, клиент сначала говорит 'read' т.е. можно читать
                          сервер шлёт данные
                          клиент показывает read error по истечению таймаута
                          ExpandedWrap disabled
                            send(sock, "identifier=1z2y3z \r\n", 22, 0);// шлем лабудень
                                tv2.tv_sec = 7;
                                FD_ZERO(&readfds);
                                FD_SET(sock, &readfds);
                                rc = select(sock, &readfds, NULL, NULL, &tv2);
                                {printf("read\n");
                             
                                ioctlsocket( sock, FIONREAD, &argp);
                               if (argp==0) {
                               // противоположная сторона закрыла сокет или отвалилась
                               closesocket(sock);
                               printf("read error\n");
                               return;  
                               } else {
                               // в противном сдучае выдираем данные из сокета. Да, argp - количество байт, которые надо выдрать ресивом
                               bytesRcvd = recv(sock, echoBuffer, argp, 0);
                                   printf("received %d bytes\n", bytesRcvd);
                                  printf("%s\n", echoBuffer);
                                
                               }}

                          необходимо асинхронное чтение:
                          Цитата
                          сервер отослал данные
                          клиент принял
                          клиент отобразил не порвав соединение
                          Сообщение отредактировано: sign63 -
                            Вот вам пример:
                            ExpandedWrap disabled
                              #include <stdio.h>
                              #include <winsock2.h>
                              // port to connect to
                              #define PORT 3490
                              // maximum ammount of data to receive
                              #define MAXDATASIZE 1000
                              int main(int argc, char* argv[])
                              {
                                  struct hostent*     he;
                                  struct sockaddr_in  addr;
                                  int         sock, received;
                                  char            buffer[MAXDATASIZE + 1];
                                  WSADATA         wsa_data;
                                  // check parameters count
                                  if ( argc != 2 )
                                  {
                                      fprintf( stderr, "Usage: client <hostname>\n" );
                                      exit( 1 );
                                  }
                                  // init win sock library
                                  WSAStartup( MAKEWORD( 1, 1 ), &wsa_data );
                                  // resolve host name
                                  if ( ( he = gethostbyname( argv[1] ) ) == NULL )
                                  {
                                      fprintf( stderr, "Failed to resolve host name\n" );
                                      exit( 1 );
                                  }
                                  // create socket
                                  if ( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
                                  {
                                      fprintf( stderr, "Failed creating socket\n" );
                                      exit( 1 );
                                  }
                                  // switch socket to non-blocking mode
                                  unsigned long l = 1;
                                  if ( ioctlsocket( sock, FIONBIO, &l ) != 0 )
                                  {
                                      fprintf( stderr, "Failed setting socket to non-blocking mode\n" );
                                      closesocket( sock );
                                      exit( 1 );
                                  }
                                  //
                                  memset( &addr, 0, sizeof( addr ) );
                                  // set remote addres
                                  addr.sin_family = AF_INET;
                                  addr.sin_port   = htons( PORT );
                                  addr.sin_addr   = *((struct in_addr*) he->h_addr_list[0]);
                                  // connect to server
                                  if ( connect( sock, (sockaddr*) &addr, sizeof( sockaddr ) ) == SOCKET_ERROR )
                                  {
                                      int error = WSAGetLastError( );
                                      if ( ( error != WSAEWOULDBLOCK ) && ( error != WSAEINPROGRESS ) )
                                      {
                                          fprintf( stderr, "Failed connecting to remote host, %d\n", error );
                                          closesocket( sock );
                                          exit( 1 );
                                      }
                                  }
                                  //
                                  fd_set read_set, error_set;
                                  struct timeval tv;
                                  // wait for a message
                                  for ( ; ; )
                                  {
                                      tv.tv_sec = 1;
                                      tv.tv_usec = 0;
                                      // fill sets
                                      FD_ZERO( &read_set );
                                      FD_ZERO( &error_set );
                                      FD_SET( sock, &read_set );
                                      FD_SET( sock, &error_set );
                                      //
                                      if ( select( sock + 1, &read_set, NULL, &error_set, &tv ) == 1 )
                                      {
                                          // check for error
                                          if ( FD_ISSET( sock, &error_set ) )
                                          {
                                              int error, error_len = sizeof( error );
                                              getsockopt( sock, SOL_SOCKET, SO_ERROR, (char*) &error, &error_len );
                                              fprintf( stderr, "\nError on socket (error: %d)\n", error );
                                          }
                               
                                          // check for message
                                          if ( FD_ISSET( sock, &read_set ) )
                                          {
                                              // receive some data from server
                                              if ( ( received = recv( sock, buffer, MAXDATASIZE, 0 ) ) == SOCKET_ERROR )
                                              {
                                                  fprintf( stderr, "Failed receiving data\n" );
                                              }
                                              else
                                              {
                                                  buffer[received] = '\0';
                                                  // display the message
                                                  printf( "\nYep! I got a message: %s\n", buffer );
                                              }
                                          }
                               
                                          break;
                                      }
                                      printf( "." );
                                  }
                                  // close socket
                                  closesocket( sock );
                                  // and say good bye to the world
                                  return 0;
                              }


                            Добавлено
                            А вот это - нонсенс:
                            ExpandedWrap disabled
                              ioctlsocket( sock, FIONREAD, &argp);
                                 if (argp==0) {
                                 // противоположная сторона закрыла сокет или отвалилась
                                 closesocket(sock);
                                 printf("read error\n");
                                 return;

                            argp - это аргумент команды - и его с нулем сравнивать?????????????

                            А для постоянного чтения - нужно висеть в цикле recv() - до получения нуля от сервера - т.е. сервер все передал - и больше не хочет с вами иметь дело :D - если буфер recv() не может принять всего сообщения сразу.
                            Или просто с большим буфером - ожидать всего сообщения и смотреть на ноль.....
                            Если в цикле есть select() - то его надо заново инициализировать...
                            В общем, надо "въехать" :) в протокол общения - если это например HTTP....
                              Цитата Oleg2004 @
                              Добавлено
                              А вот это - нонсенс:
                              ExpandedWrap disabled
                                ioctlsocket( sock, FIONREAD, &argp);
                                   if (argp==0) {
                                   // противоположная сторона закрыла сокет или отвалилась
                                   closesocket(sock);
                                   printf("read error\n");
                                   return;

                              argp - это аргумент команды - и его с нулем сравнивать?????????????

                              а как же аргумент &nonblocking у меня выше? у него же тоже есть значение. так же как и у &argp
                              Определить разрыв tcp соединение
                              сообщение №2

                              Добавлено
                              а чеит оно не комплится :blink:
                              Цитата
                              Компиляция...
                              winsock.c
                              ..\..\..\..\..\Рабочий стол\winsock.c(35) : error C2143: синтаксическая ошибка: отсутствие ";" перед "тип"
                              ..\..\..\..\..\Рабочий стол\winsock.c(36) : error C2065: l: необъявленный идентификатор
                              ..\..\..\..\..\Рабочий стол\winsock.c(49) : error C2065: sockaddr: необъявленный идентификатор
                              ..\..\..\..\..\Рабочий стол\winsock.c(49) : error C2059: синтаксическая ошибка: )
                              ..\..\..\..\..\Рабочий стол\winsock.c(52) : error C2065: error: необъявленный идентификатор
                              ..\..\..\..\..\Рабочий стол\winsock.c(52) : error C2065: error: необъявленный идентификатор
                              ..\..\..\..\..\Рабочий стол\winsock.c(54) : error C2065: error: необъявленный идентификатор
                              ..\..\..\..\..\Рабочий стол\winsock.c(60) : error C2061: синтаксическая ошибка: идентификатор "read_set"
                              ..\..\..\..\..\Рабочий стол\winsock.c(60) : error C2059: синтаксическая ошибка: ;
                              ..\..\..\..\..\Рабочий стол\winsock.c(60) : error C2059: синтаксическая ошибка: ,
                              ..\..\..\..\..\Рабочий стол\winsock.c(63) : error C2059: синтаксическая ошибка: for
                              ..\..\..\..\..\Рабочий стол\winsock.c(63) : error C2059: синтаксическая ошибка: )
                              ..\..\..\..\..\Рабочий стол\winsock.c(64) : error C2449: имеется '{' в пределах области видимости файла (возможно, отсутствует заголовок функции)
                              ..\..\..\..\..\Рабочий стол\winsock.c(102) : error C2059: синтаксическая ошибка: }
                              ..\..\..\..\..\Рабочий стол\winsock.c(106) : error C2059: синтаксическая ошибка: return
                              ..\..\..\..\..\Рабочий стол\winsock.c(107) : error C2059: синтаксическая ошибка: }


                              Добавлено
                              эт чтобы посмотреть как на пример, а не реально работающая программка я так понял
                                Я не слышал о таком способе определения завершения TCP-сессии.
                                FIONREAD применяется для определения количества байтов, пришедших в буфер tcp-сокета.
                                При этом буфер не очищается.
                                Но значение нуля - в буфер никогда не помещается.
                                Это так сделан recv() - его реакция на сегмент FIN приводит к возврату нуля - но это никак не количество байтов - равное нулю!!!!!!!!!

                                Добавлено
                                У меня скомпилилась в момент :yes: - и это никакая не демо - а работающий клиент :angry:
                                Client\Client.cpp
                                  Цитата Oleg2004 @
                                  Добавлено
                                  У меня скомпилилась в момент :yes: - и это никакая не демо - а работающий клиент :angry:
                                  Client\Client.cpp

                                  а так оно на C++ :( У меня клиент на си, попробую часть под себя подстроить
                                  Сообщение отредактировано: sign63 -
                                  1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                  0 пользователей:
                                  Страницы: (3) 1 [2] 3  все


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0520 ]   [ 15 queries used ]   [ Generated: 19.05.24, 00:01 GMT ]