Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[52.14.45.36] |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
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 @ 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++ У меня клиент на си, попробую часть под себя подстроить |