Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Сетевое программирование > nonblocking sockets C (си)


Автор: sign63 07.02.10, 17:50
доброго времени суток, уважаемые.
писал программку на Си - что то отдалённо напоминающее хттп клиент
должна отправаить запрос и принимть ответы сервера.
доп зависимости в линкере wsock32.lib Ws2_32.lib
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <stdio.h>      /* for printf(), fprintf() */
    #include <winsock.h>    /* for socket(),... */
    #include <stdlib.h>     /* for exit() */
     
    #define RCVBUFSIZE 32   /* Size of receive buffer */
     
    void DieWithError(char *errorMessage){
        perror(errorMessage);
        exit(0);
    };  /* Error handling function */
     
    void main(int argc, char *argv[])
    {
        int sock;                        /* Socket descriptor */
        struct sockaddr_in echoServAddr; /* Echo server address */
        unsigned short echoServPort;     /* Echo server port */
        char *servIP;                    /* Server IP address (dotted quad) */
        
        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;
        if ((argc < 2) || (argc > 3))    /* Test for correct number of arguments */
        {
            fprintf(stderr, "Usage: %s <Server IP> <Echo Port>\n", argv[0]);
            exit(1);
        }
     
        servIP = argv[1];             /* First arg: server IP address (dotted quad) */
      echoServPort = argv[2];         /* Second arg: server port */
     
      
        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 */
        /* Establish the connection to the echo server */
        if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
            DieWithError("connect() failed");
     
        echoStringLen = strlen(echoString);          /* Determine input length */
     
        /* Send the string, including the null terminator, to the server */
        if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
            DieWithError("send() sent a different number of bytes than expected");
     
        /* Receive the same string back from the server */
        totalBytesRcvd = 0;
        printf("Received: ");                /* Setup to print the echoed string */
        while (totalBytesRcvd < echoStringLen)
        {
            /* Receive up to the buffer size (minus 1 to leave space for
               a null terminator) bytes from the sender */
            if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
                DieWithError("recv() failed or connection closed prematurely");
            totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
            echoBuffer[bytesRcvd] = '\0';  /* Add \0 so printf knows where to stop */
            printf("%s", echoBuffer);            /* Print the echo buffer */
        }
     
        printf("\n");    /* Print a final linefeed */
     
        closesocket(sock);
        WSACleanup();  /* Cleanup Winsock */
     
        exit(0);
    }

при коннекте "program.exe host port"
ошибка соединения, почему не понимаю
connect () failed: no error
прошу помощи в разъяснении

Автор: Паровоз 07.02.10, 18:10
Цитата
If no error occurs, connect returns zero. Otherwise, it returns SOCKET_ERROR, and a specific error code can be retrieved by calling WSAGetLastError.

On a blocking socket, the return value indicates success or failure of the connection attempt.


With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. In this case, there are three possible scenarios:

Use the select function to determine the completion of the connection request by checking to see if the socket is writeable.
If the application is using WSAAsyncSelect to indicate interest in connection events, then the application will receive an FD_CONNECT notification indicating that the connect operation is complete (successfully or not).
If the application is using WSAEventSelect to indicate interest in connection events, then the associated event object will be signaled indicating that the connect operation is complete (successfully or not).


Короче, в неблокирующем режиме, он может сразу не подключиться, возвращая WSAEWOULDBLOCK. Всго лишь нужно подождать, либо использовать select для того, чтобы убедиться в завершенности операции.

Автор: sign63 07.02.10, 18:48
в смысле подождать

Автор: Паровоз 07.02.10, 19:44
Если программа несерьезная, можно вставить sleep после connect, когда - нибудь соединение да произойдет, если сервер доступен.
Но лучше так не делать и использовать WSAAsyncSelect c флагом события FD_CONNECT.

Автор: sign63 07.02.10, 20:23
поменял
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    echoServPort = argv[2];

на
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    echoServPort = atoi(argv[2]);

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ..
    #include <unistd.h>
    ..
    ..
    /* Create a reliable, stream socket using TCP */
        if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) < 0)
            DieWithError("socket() failed");
     
    sleep(5);
     
     
        /* Set the socket to nonblocking */
        if (ioctlsocket(sock, FIONBIO, &nonblocking) != 0)
            DieWithError("ioctlsocket() failed");
     
    ..
    ..

Не удается открыть файл include: unistd.h: No such file or directory
Этж только под никсами... а на мастдае как?

и еще: как с WSAAsyncSelect сделать? можно на примере моей проги показать?
Или киньте ссылку, где подробно расписано о WSAAsyncSelect для Си

Автор: sign63 07.02.10, 23:45
подправил. теперь c select. ждет 2.5 секунды и выходит :D
Программа "[2312] у3к6.exe: Машинный код" завершилась с кодом 0 (0x0).
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <stdio.h>      /* for printf(), fprintf() */
    #include <winsock.h>    /* for socket(),... */
    #include <stdlib.h>     /* for exit() */
    #include <time.h>
    #include <sys/types.h>
     
    #define RCVBUFSIZE 32   /* Size of receive buffer */
     
    void DieWithError(char *errorMessage){
        perror(errorMessage);
        exit(0);
    };  /* Error handling function */
     
    void main(int argc, char *argv[])
    {
        int sock, rc, read_fds, echoServPort;                      
        struct sockaddr_in echoServAddr;
    //    unsigned short echoServPort;    
        char *servIP;                    
        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;
        struct timeval tv;
        fd_set readfds;
        tv.tv_sec = 2;
        tv.tv_usec = 500000;
      
        servIP = argv[1];             /* First arg: server IP address (dotted quad) */
      
        // echoServPort = atoi(argv[2]); /* Use given port, if any */
      echoServPort = 8088;
        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 */
        
        FD_ZERO(&readfds);
        FD_SET(sock, &readfds);
        rc = select(sock, &readfds, NULL, NULL, &tv);
        if((rc == 1) && (FD_ISSET(sock, &read_fds)))
    {
        /* Establish the connection to the echo server */
        if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
            DieWithError("connect() failed");
        
        echoStringLen = strlen(echoString);          /* Determine input length */
     
        /* Send the string, including the null terminator, to the server */
        if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
            DieWithError("send() sent a different number of bytes than expected");
     
        /* Receive the same string back from the server */
        totalBytesRcvd = 0;
        printf("Received: ");                /* Setup to print the echoed string */
        while (totalBytesRcvd < echoStringLen)
        {
            /* Receive up to the buffer size (minus 1 to leave space for
               a null terminator) bytes from the sender */
            if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
                DieWithError("recv() failed or connection closed prematurely");
            totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
            echoBuffer[bytesRcvd] = '\0';  /* Add \0 so printf knows where to stop */
            printf("%s", echoBuffer);            /* Print the echo buffer */
        }
        }
     
     
        printf("\n");    /* Print a final linefeed */
     
        closesocket(sock);
        WSACleanup();  /* Cleanup Winsock */
     
        exit(0);
    }

Автор: Паровоз 08.02.10, 05:08
Ты бы поспал :)
В твоем случае
rc = select(sock, &readfds, NULL, NULL, &tv);
ожидает, когда в сокет придут данные, сокет, который даже не подключен (connect ниже).
select нужно использовать не для ожидания того, когда он будет готов для чтения, а для ожидания того, когда он будет готов для записи. А это другой параметр.
удачи!

Автор: sign63 08.02.10, 10:13
:wall: таже фигня
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <stdio.h>      /* for printf(), fprintf() */
    #include <winsock.h>    /* for socket(),... */
    #include <stdlib.h>     /* for exit() */
    #include <time.h>
    #include <sys/types.h>
     
    #define RCVBUFSIZE 32   /* 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 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;
        struct timeval tv;
        tv.tv_sec = 2;
        tv.tv_usec = 500000;
        servIP =  argv[1];             /* First arg: server IP address (dotted quad) */
        echoServPort =  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 */
        
        FD_ZERO(&writefds);
        FD_SET(sock, &writefds);
        rc = select(sock, NULL, &writefds, NULL, &tv);
        if((rc == 1) && (FD_ISSET(sock, &writefds)))
    {
        /* Establish the connection to the echo server */
        if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
            DieWithError("connect() failed");
        
        echoStringLen = strlen(echoString);          /* Determine input length */
     
        /* Send the string, including the null terminator, to the server */
        if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
            DieWithError("send() sent a different number of bytes than expected");
     
        /* Receive the same string back from the server */
        totalBytesRcvd = 0;
        printf("Received: ");                /* Setup to print the echoed string */
        while (totalBytesRcvd < echoStringLen)
        {
            /* Receive up to the buffer size (minus 1 to leave space for
               a null terminator) bytes from the sender */
            if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
                DieWithError("recv() failed or connection closed prematurely");
            totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
            echoBuffer[bytesRcvd] = '\0';  /* Add \0 so printf knows where to stop */
            printf("%s", echoBuffer);            /* Print the echo buffer */
        }
        }
     
     
        printf("\n");    /* Print a final linefeed */
     
        closesocket(sock);
        WSACleanup();  /* Cleanup Winsock */
     
        exit(0);
    }

Автор: kolobok0 08.02.10, 10:16
Цитата sign63 @
...
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ...
        while (totalBytesRcvd < echoStringLen)
        {
    ....
            if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
    ...
            totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
            echoBuffer[bytesRcvd] = '\0';  /* Add \0 so printf knows where to stop */
    ..
        }
    ...

не понятна следующая логика.
1) цикл на общую длину.
2) идёт перезатирка ранее принятых данных.

так вам что нуна то?
Приём по кусочкам на которые раздробил данные нижний уровень(или вы в передатчике) или приём полной длины эхо строки?

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

увеличьте строку скажем до пары метров.


удачи вам
(круглый)

Автор: sign63 08.02.10, 10:44
Цитата kolobok0 @
Цитата sign63 @
...
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ...
        while (totalBytesRcvd < echoStringLen)
        {
    ....
            if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
    ...
            totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
            echoBuffer[bytesRcvd] = '\0';  /* Add \0 so printf knows where to stop */
    ..
        }
    ...

не понятна следующая логика.
1) цикл на общую длину.
2) идёт перезатирка ранее принятых данных.

так вам что нуна то?
Приём по кусочкам на которые раздробил данные нижний уровень(или вы в передатчике) или приём полной длины эхо строки?

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

увеличьте строку скажем до пары метров.


удачи вам
(круглый)

над приемом данных еще подумаю, но проблема сейчас пока что в коннекте к серверу, надо её сначало решить

Автор: Oleg2004 08.02.10, 12:02
Цитата sign63 @
доп зависимости в линкере wsock32.lib Ws2_32.lib

Зачем линкуете сразу две библиотеки?
Вы работаете с версией винсок 2.0

(WSAStartup(MAKEWORD(2, 0), &wsaData)

- потому только Ws2_32.lib
и еще - winsock2.h

Автор: sign63 08.02.10, 13:18
Цитата Oleg2004 @
Цитата sign63 @
доп зависимости в линкере wsock32.lib Ws2_32.lib

Зачем линкуете сразу две библиотеки?
Вы работаете с версией винсок 2.0

(WSAStartup(MAKEWORD(2, 0), &wsaData)

- потому только Ws2_32.lib
и еще - winsock2.h

просто были траблы на ранней части написания, в каком то из мануалов вымсмотрел.
убрал лишнюю wsock32.lib, поправил winsock.h на winsock2.h

нашёл WWinsock Interface Library for C/C++ 3.1
там куча примеров, есть то что мне надо async.c
но не компилируется, зараза в visual studio. по идее такие как эти проекты (стоимость 130$ на офф сайте)
должны сразу без проблем компилится

Цитата
Компиляция...
ASYNC.C
z:\wil4c\ASYNC.C(69) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPWSTR'
z:\wil4c\ASYNC.C(69) : warning C4133: функция: несовместимые типы - из 'char [17]' в 'LPCWSTR'
z:\wil4c\ASYNC.C(95) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPWSTR'
z:\wil4c\ASYNC.C(95) : warning C4133: функция: несовместимые типы - из 'char [29]' в 'LPCWSTR'
z:\wil4c\ASYNC.C(146) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPWSTR'
z:\wil4c\ASYNC.C(146) : warning C4133: функция: несовместимые типы - из 'char [17]' в 'LPCWSTR'
z:\wil4c\ASYNC.C(167) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPWSTR'
z:\wil4c\ASYNC.C(167) : warning C4133: функция: несовместимые типы - из 'char [25]' в 'LPCWSTR'
z:\wil4c\ASYNC.C(176) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPCWSTR'
z:\wil4c\ASYNC.C(192) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPWSTR'
z:\wil4c\ASYNC.C(192) : warning C4133: функция: несовместимые типы - из 'char [30]' в 'LPCWSTR'
z:\wil4c\ASYNC.C(202) : warning C4133: функция: несовместимые типы - из 'LPSTR' в 'LPCWSTR'
Компоновка...
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilTcpSocket@0"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilMakeAddr@4"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilErrorText@12"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilReadLine@12"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilGetHostAddr@8"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "_DisplayLine"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilIsDotted@4"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilMakeDotted@12"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilWriteLine@8"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "_StringCopy"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "_DisplayString"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilConnect@12"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilParseDecimal@4"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilWaitLine@20"
ASYNC.obj : error LNK2001: неразрешенный внешний символ "__imp__wilAwaitEvent@16"
MSVCRT.lib(crtexe.obj) : error LNK2001: неразрешенный внешний символ "_main"


а miracle C ругается только на
Цитата
wil.h: line 71: Parse Error, expecting `','' or `SEP'
'SOCKET FAR'
aborting compile

Автор: sign63 08.02.10, 14:12
select возвращает 0, что говорит о истекшем тайм ауте
а значения sin_port, echoServAddr.sin_port разве должны быть такими?
user posted image

Автор: Oleg2004 08.02.10, 14:31
Цитата sign63 @
а значения sin_port, echoServAddr.sin_port разве должны быть такими?

Они преобразованы ы порядок сети - а выводятся в порядке хоста.

Автор: sign63 08.02.10, 15:27
как сказал мне один форумчанин:
Цитата
в данной ситуации позволяет дождаться, когда будет закончено выполнение предыдущей операции. Пока коннект с сервером не установлен, ни о какой отправке данных речи быть не может, поэтому ждём:select (sock, NULL, &writefds, NULL, &tv); потом говорим write, и хотим прочитать ответ. Но пока ответ не пришёл, читать бессмысленно. Поэтому select (sock, &readfds, NULL, NULL, &tv); и только потом read.

Автор: Oleg2004 08.02.10, 15:45
Цитата sign63 @
не открывается соединение.

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

Автор: Паровоз 08.02.10, 18:15
Слабо поменять местами?
Вот так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    {
        /* 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 08.02.10, 19:17
Цитата Oleg2004 @
Цитата sign63 @
не открывается соединение.

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

это ip хоста внутренней сети для доступа winxp из виртуалки к серверу на убунте (хосту)
Добавлено
Цитата Паровоз @
Слабо поменять местами?
Вот так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    {
        /* 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");
        }

я сначала не заметил вторую страницу, решил проблему - сделал также как ты написал.

Автор: nemez 08.02.10, 19:49
кто здесь, кто здесь??? :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 и наслаждаемся. Пардон, пишу левой ногой без телячьих нежностей ввиду отсутсвия времени. Чуть покорячу приведенный код - увеличу буфер и напишу как нада коннектиться. Не пинать типа "а чё ты не проверил что коннект вернул сокет_еррор" и т.п. Все детали - мсдн.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #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>

Автор: sign63 08.02.10, 19:56
Цитата nemez @

Чтож ты раньше не пришел <_<
а мсдн я смотрел, да. жаль там примеры на cpp

Автор: Паровоз 08.02.10, 20:13
Цитата
я сначала не заметил вторую страницу, решил проблему - сделал также как ты написал.

Я тебе с утра еще об этом написал. Ночью спать надо ;)

Автор: sign63 08.02.10, 20:48
Цитата 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>

а результат приходит только когда сервер разорвет соединение :(

Автор: nemez 08.02.10, 20:56
ответ неправильный. Щас напишу как оно есть на самом деле.

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

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

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

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

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

только наоборот
Линукс:
ioctl( Socket, FIONREAD, &argp );
Мастдай:
ioctlsocket( Socket, FIONREAD, &argp );

Автор: Паровоз 09.02.10, 05:29
еще вспомним
fcntl(sockfd, F_SETFL, O_NONBLOCK);
вариантов масса.

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

Еще забыл про -1 в неблокирующих. Значит, что ничего не пришло.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
        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
    .....

Примерно таким куском я обычно пользуюсь

Автор: sign63 09.02.10, 10:26
Цитата 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 по истечению таймаута
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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);
        
       }}

необходимо асинхронное чтение:
Цитата
сервер отослал данные
клиент принял
клиент отобразил не порвав соединение

Автор: Oleg2004 09.02.10, 11:03
Вот вам пример:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #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;
    }


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

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

А для постоянного чтения - нужно висеть в цикле recv() - до получения нуля от сервера - т.е. сервер все передал - и больше не хочет с вами иметь дело :D - если буфер recv() не может принять всего сообщения сразу.
Или просто с большим буфером - ожидать всего сообщения и смотреть на ноль.....
Если в цикле есть select() - то его надо заново инициализировать...
В общем, надо "въехать" :) в протокол общения - если это например HTTP....

Автор: sign63 09.02.10, 11:25
Цитата Oleg2004 @
Добавлено
А вот это - нонсенс:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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: синтаксическая ошибка: }


Добавлено
эт чтобы посмотреть как на пример, а не реально работающая программка я так понял

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

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

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

а так оно на C++ :( У меня клиент на си, попробую часть под себя подстроить

Автор: dikdik 09.02.10, 12:38
У Вас больше проблема с путями к заголовочным файлам. Потому и не компилится. А пример чистый С.

Автор: Oleg2004 09.02.10, 12:43
Да особой разницы то я и не вижу - с и спп :D

Добавлено
Цитата dikdik @
А пример чистый С.

Это точно.....поэтому я и не видел разницы :D
Чистый С в Студии компилится как спп без проблем.....во всяком случае у меня.
А по ошибкам - да, видимо нет доступа к описанию элементарных типов......

Автор: sign63 09.02.10, 13:36
стартует, открывает соединение, ждет tv и выдает <cenzored>точек
всё. поправил, теперь всё работает
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <stdio.h>      /* for printf(), fprintf() */
    #include <winsock2.h>    /* for socket(),... */
    #include <stdlib.h>     /* for exit() */
    #include <time.h>
    #include <sys/types.h>
    #define MAXDATASIZE 1000
    #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[] = "10.0.2.2";
        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, error_set;
        struct timeval tv;
        tv.tv_sec = 5;
        tv.tv_usec = 500000;
        //servIP =  argv[1];             /* First arg: server IP address (dotted quad) */
        echoServPort = 8088; //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, "identifier=1z2y3z \r\n\r\n", 26, 0);// шлем id
     
        
        for ( ; ; )
        {
           FD_ZERO(&readfds);
        FD_ZERO(&error_set);
        FD_SET(sock, &readfds);
        FD_SET(sock, &error_set);
            //
            if ( select( sock, &readfds, 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, &readfds ) )
                {
                    // receive some data from server
                    if ( ( bytesRcvd = recv( sock, echoBuffer, MAXDATASIZE, 0 ) ) == SOCKET_ERROR )
                    {
                        fprintf( stderr, "Failed receiving data\n" );
                    }
                    else
                    {
                        echoBuffer[bytesRcvd] = '\0';
                        // display the message
                        printf( "\nYep! I got a message: %s\n", echoBuffer );
                    }
                }
     
                break;
            }
            printf( "." );
        }
      
        WSACleanup();  // Cleanup Winsock
    }

user posted image
Добавлено
Цитата Oleg2004 @
Да особой разницы то я и не вижу - с и спп :D

Добавлено
Цитата dikdik @
А пример чистый С.

Это точно.....поэтому я и не видел разницы :D
Чистый С в Студии компилится как спп без проблем.....во всяком случае у меня.
А по ошибкам - да, видимо нет доступа к описанию элементарных типов......

Добавлено
Цитата dikdik @
У Вас больше проблема с путями к заголовочным файлам. Потому и не компилится. А пример чистый С.

так я тоже думал что оно Си'шное. *.c не компилится, а с *.cpp компилится. Всё таки проблема с путями/доступом_к_описанию_элементарных_типов или то написано на C++?

Автор: nemez 09.02.10, 14:04
странно. У меня собирается как под расширением си, так и под расширением сипипи. Как под борландом, так и под майкрософтом.
И приведенный код работает. Как это не странно. Я опять коннекчусь на яндекс, отправляю эту дребездень которая идентифаер стринг, и получаю 400й код.
Из неправильного - перед каждым селектом надо делать FD_SET. Нужно обнулять массивы директивой FD_ZERO либо в конце основного цикла, либо в начале..
короче, всю эту требуху
Цитата
FD_ZERO(&readfds);
FD_ZERO(&error_set);
FD_SET(sock, &readfds);
FD_SET(sock, &error_set);

нужно в основной цикл, сразу за фореву

Автор: sign63 09.02.10, 15:07
Цитата nemez @
странно. У меня собирается как под расширением си, так и под расширением сипипи. Как под борландом, так и под майкрософтом.
И приведенный код работает. Как это не странно. Я опять коннекчусь на яндекс, отправляю эту дребездень которая идентифаер стринг, и получаю 400й код.
Из неправильного - перед каждым селектом надо делать FD_SET. Нужно обнулять массивы директивой FD_ZERO либо в конце основного цикла, либо в начале..
короче, всю эту требуху
Цитата
FD_ZERO(&readfds);
FD_ZERO(&error_set);
FD_SET(sock, &readfds);
FD_SET(sock, &error_set);

нужно в основной цикл, сразу за фореву

сбросы и сеты поправил.
на яндексе код заработал. и на серве вроде тоже заработал.

Автор: Oleg2004 09.02.10, 15:26
Цитата nemez @
нужно в основной цикл, сразу за фореву

Я как раз об этом предупреждал :yes:
Это известная фишка селекта - после единственного срабатывания - все маски событий сбрасываются - и их надо восстанавливать снова..... :)
Поэтому тут и пишется
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    for ( ; ; )
        {
        FD_ZERO(&readfds);
        FD_ZERO(&error_set);
        FD_SET(sock, &readfds);
        FD_SET(sock, &error_set);

.............
Ну а насчет как работает....
Так этот код не был заточен под HTTP - естественно надо видоизменять......
Теперь ваша задача - прочувствовать код......это сетевое программирование - а не хухры мухры.... :yes:

Автор: sign63 09.02.10, 20:18
а еще вопрос.
принял я эти данные, хочу продолжать принимать дальше. комментирую break
программа сначала ждет принятия данных, каждые &tv печатает по точке, потом когда данные отосланы, принимает их, распечатывает, возвращается к select, он ей что то говорит и она пропускает чтение - начинает просто бесконечно из-за for (;;) ставить точки без всяких таймаутов. а что нужно сделать чтобы опять ждала принятия данных?

Автор: nemez 09.02.10, 20:44
селект возвращает единицу если он успешно отработал. Если селект вылетел по таймауту - он возвращает ноль. Если случилась ошибка - он возвращает отрицательный результат.
Точка у тебя печатается не по таймауту, а по любому из трех событий - прием данных, ошибка, таймаут. Это первое.
Чтобы оно не ставило точки - закоментируй принтф. Чтобы оно не вылетало по таймауту - передай в селект в качестве последнего аргумента ноль.

Автор: sign63 16.02.10, 17:10
эмм, еще вопрос - моя готовая программка на локальном компе открывает порт, всё время разный. как можно указать собственный?
вот скрин http://imm.io/4nO

Автор: Паровоз 16.02.10, 17:20
bind?

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)