Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.15.179.121] |
|
Сообщ.
#1
,
|
|
|
доброго времени суток, уважаемые.
писал программку на Си - что то отдалённо напоминающее хттп клиент должна отправаить запрос и принимть ответы сервера. доп зависимости в линкере wsock32.lib Ws2_32.lib #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 прошу помощи в разъяснении |
Сообщ.
#2
,
|
|
|
Цитата 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 для того, чтобы убедиться в завершенности операции. |
Сообщ.
#3
,
|
|
|
в смысле подождать
|
Сообщ.
#4
,
|
|
|
Если программа несерьезная, можно вставить sleep после connect, когда - нибудь соединение да произойдет, если сервер доступен.
Но лучше так не делать и использовать WSAAsyncSelect c флагом события FD_CONNECT. |
Сообщ.
#5
,
|
|
|
поменял
echoServPort = argv[2]; на echoServPort = atoi(argv[2]); .. #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 для Си |
Сообщ.
#6
,
|
|
|
подправил. теперь c select. ждет 2.5 секунды и выходит
Программа "[2312] у3к6.exe: Машинный код" завершилась с кодом 0 (0x0). #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); } |
Сообщ.
#7
,
|
|
|
Ты бы поспал
В твоем случае rc = select(sock, &readfds, NULL, NULL, &tv); ожидает, когда в сокет придут данные, сокет, который даже не подключен (connect ниже). select нужно использовать не для ожидания того, когда он будет готов для чтения, а для ожидания того, когда он будет готов для записи. А это другой параметр. удачи! |
Сообщ.
#8
,
|
|
|
таже фигня
#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); } |
Сообщ.
#9
,
|
|
|
Цитата sign63 @ ... ... 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) идёт перезатирка ранее принятых данных. так вам что нуна то? Приём по кусочкам на которые раздробил данные нижний уровень(или вы в передатчике) или приём полной длины эхо строки? это не будет понятно пока у вас строка маленькая, работаете не в боевой сети и на нагрузках типа хэлохты мир. увеличьте строку скажем до пары метров. удачи вам (круглый) |
Сообщ.
#10
,
|
|
|
Цитата kolobok0 @ Цитата sign63 @ ... ... 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) идёт перезатирка ранее принятых данных. так вам что нуна то? Приём по кусочкам на которые раздробил данные нижний уровень(или вы в передатчике) или приём полной длины эхо строки? это не будет понятно пока у вас строка маленькая, работаете не в боевой сети и на нагрузках типа хэлохты мир. увеличьте строку скажем до пары метров. удачи вам (круглый) над приемом данных еще подумаю, но проблема сейчас пока что в коннекте к серверу, надо её сначало решить |
Сообщ.
#11
,
|
|
|
Цитата sign63 @ доп зависимости в линкере wsock32.lib Ws2_32.lib Зачем линкуете сразу две библиотеки? Вы работаете с версией винсок 2.0 (WSAStartup(MAKEWORD(2, 0), &wsaData) - потому только Ws2_32.lib и еще - winsock2.h |
Сообщ.
#12
,
|
|
|
Цитата 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 |
Сообщ.
#13
,
|
|
|
Сообщ.
#14
,
|
|
|
Цитата sign63 @ а значения sin_port, echoServAddr.sin_port разве должны быть такими? Они преобразованы ы порядок сети - а выводятся в порядке хоста. |
Сообщ.
#15
,
|
|
|
как сказал мне один форумчанин:
Цитата в данной ситуации позволяет дождаться, когда будет закончено выполнение предыдущей операции. Пока коннект с сервером не установлен, ни о какой отправке данных речи быть не может, поэтому ждём:select (sock, NULL, &writefds, NULL, &tv); потом говорим write, и хотим прочитать ответ. Но пока ответ не пришёл, читать бессмысленно. Поэтому select (sock, &readfds, NULL, NULL, &tv); и только потом read. |
Сообщ.
#16
,
|
|
|
Цитата sign63 @ не открывается соединение. char servIP[] = "10.42.43.1"; Этот IP - где он находится? В вашей локальной сети? И после connect() обязательно поставить WSAGetLastError() - без кода ошибки при соединении - узнать истинную причину невозможно. Это закон сетевого программирования - WSAGetLastError() после каждой сетевой функции. Например: r = recv(...); if (r == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) |
Сообщ.
#17
,
|
|
|
Слабо поменять местами?
Вот так: { /* 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"); } |
Сообщ.
#18
,
|
|
|
Цитата Oleg2004 @ Цитата sign63 @ не открывается соединение. char servIP[] = "10.42.43.1"; Этот IP - где он находится? В вашей локальной сети? И после connect() обязательно поставить WSAGetLastError() - без кода ошибки при соединении - узнать истинную причину невозможно. Это закон сетевого программирования - WSAGetLastError() после каждой сетевой функции. Например: r = recv(...); if (r == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) это ip хоста внутренней сети для доступа winxp из виртуалки к серверу на убунте (хосту) Добавлено Цитата Паровоз @ Слабо поменять местами? Вот так: { /* 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"); } я сначала не заметил вторую страницу, решил проблему - сделал также как ты написал. |
Сообщ.
#19
,
|
|
|
кто здесь, кто здесь???
вот почему Цитата 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 и наслаждаемся. Пардон, пишу левой ногой без телячьих нежностей ввиду отсутсвия времени. Чуть покорячу приведенный код - увеличу буфер и напишу как нада коннектиться. Не пинать типа "а чё ты не проверил что коннект вернул сокет_еррор" и т.п. Все детали - мсдн. #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> |
Сообщ.
#20
,
|
|
|
Цитата nemez @ Чтож ты раньше не пришел а мсдн я смотрел, да. жаль там примеры на cpp |
Сообщ.
#21
,
|
|
|
Цитата я сначала не заметил вторую страницу, решил проблему - сделал также как ты написал. Я тебе с утра еще об этом написал. Ночью спать надо |
Сообщ.
#22
,
|
|
|
Цитата 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> а результат приходит только когда сервер разорвет соединение |
Сообщ.
#23
,
|
|
|
ответ неправильный. Щас напишу как оно есть на самом деле.
Добавлено прежде, чем выдирать из сокета байты, нужно понимать, что там лежит. делается это так. 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); } собственно так. Тоесть, если в сокете ноль байт - это значит что сообщение разорвано. В противном случае - там есть данные, их надо оттуда выгрести и обработать |
Сообщ.
#24
,
|
|
|
@nemez откуда ты так хорошо знаешь winsock для Си? Рыл инет, колво литературы по этому предмету - стремится к нулю. А та что действительно хорошая - на английском, благо английский это не проблема
Добавлено Цитата nemez @ Винда: ioctl( Socket, FIONREAD, &argp ); Линукс: ioctlsocket( Socket, FIONREAD, &argp ); только наоборот Линукс: ioctl( Socket, FIONREAD, &argp ); Мастдай: ioctlsocket( Socket, FIONREAD, &argp ); |
Сообщ.
#25
,
|
|
|
еще вспомним
fcntl(sockfd, F_SETFL, O_NONBLOCK); вариантов масса. Цитата собственно так. Тоесть, если в сокете ноль байт - это значит что сообщение разорвано. В противном случае - там есть данные, их надо оттуда выгрести и обработать Еще забыл про -1 в неблокирующих. Значит, что ничего не пришло. 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 ..... Примерно таким куском я обычно пользуюсь |
Сообщ.
#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 по истечению таймаута 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); }} необходимо асинхронное чтение: Цитата сервер отослал данные клиент принял клиент отобразил не порвав соединение |
Сообщ.
#27
,
|
|
|
Вот вам пример:
#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; } Добавлено А вот это - нонсенс: ioctlsocket( sock, FIONREAD, &argp); if (argp==0) { // противоположная сторона закрыла сокет или отвалилась closesocket(sock); printf("read error\n"); return; argp - это аргумент команды - и его с нулем сравнивать????????????? А для постоянного чтения - нужно висеть в цикле recv() - до получения нуля от сервера - т.е. сервер все передал - и больше не хочет с вами иметь дело - если буфер recv() не может принять всего сообщения сразу. Или просто с большим буфером - ожидать всего сообщения и смотреть на ноль..... Если в цикле есть select() - то его надо заново инициализировать... В общем, надо "въехать" в протокол общения - если это например HTTP.... |
Сообщ.
#28
,
|
|
|
Цитата Oleg2004 @ Добавлено А вот это - нонсенс: ioctlsocket( sock, FIONREAD, &argp); if (argp==0) { // противоположная сторона закрыла сокет или отвалилась closesocket(sock); printf("read error\n"); return; argp - это аргумент команды - и его с нулем сравнивать????????????? а как же аргумент &nonblocking у меня выше? у него же тоже есть значение. так же как и у &argp Определить разрыв tcp соединение сообщение №2 Добавлено а чеит оно не комплится Цитата Компиляция... 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: синтаксическая ошибка: } Добавлено эт чтобы посмотреть как на пример, а не реально работающая программка я так понял |
Сообщ.
#29
,
|
|
|
Я не слышал о таком способе определения завершения TCP-сессии.
FIONREAD применяется для определения количества байтов, пришедших в буфер tcp-сокета. При этом буфер не очищается. Но значение нуля - в буфер никогда не помещается. Это так сделан recv() - его реакция на сегмент FIN приводит к возврату нуля - но это никак не количество байтов - равное нулю!!!!!!!!! Добавлено У меня скомпилилась в момент - и это никакая не демо - а работающий клиент Client\Client.cpp |
Сообщ.
#30
,
|
|
|
Цитата Oleg2004 @ Добавлено У меня скомпилилась в момент - и это никакая не демо - а работающий клиент Client\Client.cpp а так оно на C++ У меня клиент на си, попробую часть под себя подстроить |
Сообщ.
#31
,
|
|
|
У Вас больше проблема с путями к заголовочным файлам. Потому и не компилится. А пример чистый С.
|
Сообщ.
#32
,
|
|
|
Да особой разницы то я и не вижу - с и спп
Добавлено Цитата dikdik @ А пример чистый С. Это точно.....поэтому я и не видел разницы Чистый С в Студии компилится как спп без проблем.....во всяком случае у меня. А по ошибкам - да, видимо нет доступа к описанию элементарных типов...... |
Сообщ.
#33
,
|
|
|
всё. поправил, теперь всё работает #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 } Добавлено Цитата Oleg2004 @ Да особой разницы то я и не вижу - с и спп Добавлено Цитата dikdik @ А пример чистый С. Это точно.....поэтому я и не видел разницы Чистый С в Студии компилится как спп без проблем.....во всяком случае у меня. А по ошибкам - да, видимо нет доступа к описанию элементарных типов...... Добавлено Цитата dikdik @ У Вас больше проблема с путями к заголовочным файлам. Потому и не компилится. А пример чистый С. так я тоже думал что оно Си'шное. *.c не компилится, а с *.cpp компилится. Всё таки проблема с путями/доступом_к_описанию_элементарных_типов или то написано на C++? |
Сообщ.
#34
,
|
|
|
странно. У меня собирается как под расширением си, так и под расширением сипипи. Как под борландом, так и под майкрософтом.
И приведенный код работает. Как это не странно. Я опять коннекчусь на яндекс, отправляю эту дребездень которая идентифаер стринг, и получаю 400й код. Из неправильного - перед каждым селектом надо делать FD_SET. Нужно обнулять массивы директивой FD_ZERO либо в конце основного цикла, либо в начале.. короче, всю эту требуху Цитата FD_ZERO(&readfds); FD_ZERO(&error_set); FD_SET(sock, &readfds); FD_SET(sock, &error_set); нужно в основной цикл, сразу за фореву |
Сообщ.
#35
,
|
|
|
Цитата nemez @ странно. У меня собирается как под расширением си, так и под расширением сипипи. Как под борландом, так и под майкрософтом. И приведенный код работает. Как это не странно. Я опять коннекчусь на яндекс, отправляю эту дребездень которая идентифаер стринг, и получаю 400й код. Из неправильного - перед каждым селектом надо делать FD_SET. Нужно обнулять массивы директивой FD_ZERO либо в конце основного цикла, либо в начале.. короче, всю эту требуху Цитата FD_ZERO(&readfds); FD_ZERO(&error_set); FD_SET(sock, &readfds); FD_SET(sock, &error_set); нужно в основной цикл, сразу за фореву сбросы и сеты поправил. на яндексе код заработал. и на серве вроде тоже заработал. |
Сообщ.
#36
,
|
|
|
Цитата nemez @ нужно в основной цикл, сразу за фореву Я как раз об этом предупреждал Это известная фишка селекта - после единственного срабатывания - все маски событий сбрасываются - и их надо восстанавливать снова..... Поэтому тут и пишется for ( ; ; ) { FD_ZERO(&readfds); FD_ZERO(&error_set); FD_SET(sock, &readfds); FD_SET(sock, &error_set); ............. Ну а насчет как работает.... Так этот код не был заточен под HTTP - естественно надо видоизменять...... Теперь ваша задача - прочувствовать код......это сетевое программирование - а не хухры мухры.... |
Сообщ.
#37
,
|
|
|
а еще вопрос.
принял я эти данные, хочу продолжать принимать дальше. комментирую break программа сначала ждет принятия данных, каждые &tv печатает по точке, потом когда данные отосланы, принимает их, распечатывает, возвращается к select, он ей что то говорит и она пропускает чтение - начинает просто бесконечно из-за for (;;) ставить точки без всяких таймаутов. а что нужно сделать чтобы опять ждала принятия данных? |
Сообщ.
#38
,
|
|
|
селект возвращает единицу если он успешно отработал. Если селект вылетел по таймауту - он возвращает ноль. Если случилась ошибка - он возвращает отрицательный результат.
Точка у тебя печатается не по таймауту, а по любому из трех событий - прием данных, ошибка, таймаут. Это первое. Чтобы оно не ставило точки - закоментируй принтф. Чтобы оно не вылетало по таймауту - передай в селект в качестве последнего аргумента ноль. |
Сообщ.
#39
,
|
|
|
эмм, еще вопрос - моя готовая программка на локальном компе открывает порт, всё время разный. как можно указать собственный?
вот скрин http://imm.io/4nO |
Сообщ.
#40
,
|
|
|
bind?
|