| 
			| 
					
						| Денисrf | 
								|  | «  : 04-05-2010 13:03 »  |  | 
 
 Доброго времени! Вот такая проблема возникла, при создании простого эхо-сервера не получается отследить попытку подключения к сервер по получаемому IP адресу сервер-сокета. WSADATA     wsadata;SOCKET      ServerSocket;
 SOCKADDR_IN socketaddr;
 HOSTENT*    pHostent;       // Информация о хосте.
 // инициализация WinSock.
 if ((WSAStartup(MAKEWORD(2,2), &wsadata))==NULL)
 std::cout<<"Inization socket is complite"<<std::endl;
 else std::cout<<"Inization socket finished with error"<<std::endl;
 Sleep(150);
 //=====================Создание сокета==================================
 ServerSocket=socket(AF_INET,SOCK_STREAM,0);
 if (ServerSocket==INVALID_SOCKET)
 std::cout<<"INVALID_SOCKET"<<std::endl;
 else std::cout<<"ServerSocket created"<<std::endl;
 Sleep(150);
 //Заполним структуру адреса сокета на который будем его вешат
 socketaddr.sin_family=AF_INET;
 socketaddr.sin_port=PORT_ADDR;
 socketaddr.sin_addr.s_addr=0;//htons(INADDR_ANY) - принимает подключения на все IP адреса
 Sleep(150);
 //Вешаем сокет на сируктуру socketaddr
 if (bind(ServerSocket,(LPSOCKADDR)&socketaddr,sizeof(socketaddr))==SOCKET_ERROR)
 std::cout<<"Can't conect with 80 port"<<std::endl;
 else
 {
 std::cout<<"_____________________________________________________________________________"<<std::endl;
 std::cout<<"ServerSocket created: Type - SOCK_STREAM, Transport protcool - TCP, Port - 80"<<std::endl;
 std::cout<<"_____________________________________________________________________________"<<std::endl;
 }
 Sleep(150);
 
 //Перевод сокета в ждущий режим
 if (listen(ServerSocket,QUEUE_SIZE)==SOCKET_ERROR)
 std::cout<<"Server is not in listen mode"<<std::endl;
 else std::cout<<"Server is in listen mode"<<std::endl;
 
 
 pHostent = gethostbyname(chHostname);
 std::cout<<"Your IP adress: "<<inet_ntoa (*(reinterpret_cast<in_addr *>(*(pHostent->h_addr_list))))<<std::endl;
 
 
 
 SOCKET client_socket;
 sockaddr_in client_addr;    // адрес клиента
 // (заполняется системой)
 // функции accept необходимо передать размер
 // структуры
 
 int client_addr_size=sizeof(client_addr);
 while ((client_socket=accept(ServerSocket,(sockaddr *)&client_addr,&client_addr_size)))
 {
 nclients++;
 HOSTENT*    pClientHostent;
 pClientHostent=gethostbyaddr((char *)client_addr.sin_addr.s_addr,4,AF_INET);
 //std::cout<<"New conect! "<<std::endl;
 printf("+%s [%s] new connect!\n",(pClientHostent)?pClientHostent->h_name:"",inet_ntoa(client_addr.sin_addr));
 
 
 }
Если есть у кого подозрения прошу поделиться. Спасибо! |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #1 : 04-05-2010 15:42 »  |  | 
 
 Денисrf, что значит "отследить попытку подключения"?Судя по общей неаккуратности, ошибка может быть где угодно.
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #2 : 05-05-2010 12:59 »  |  | 
 
 Спасибо за замечание. Но вот что я пытаюсь сделать:Я получив IP хоста  и повесив сокет на все IP хоста пробую в опере прописать найденный IP. По идее фнкция
 
 client_socket=accept(ServerSocket,(sockaddr *)&client_addr,&client_addr_size)
 
 должна бы вернуть управления и тогда выполнится тело цикла, но этого не происходит. Почему?
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #3 : 05-05-2010 13:32 »  |  | 
 
 Зачем получать IP? Для всех IP хоста есть специальный адрес - INADDR_ANY (0.0.0.0).
 accept() вернет управление только после поступления запроса на слушающий сокет.
 
 Не нравится мне проверка ошибок: проверять надо на корректное выполнение, а не на одну определенную ошибку. Ошибки бывают разные!
 |  
						| 
								|  |  
								| « Последнее редактирование: 05-05-2010 13:35 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #4 : 05-05-2010 13:56 »  |  | 
 
 Ошибки я переработаю на проверку отрицательного значения позже, умаю так норм будет?Ну да, в структуре
 
 socketaddr.sin_addr.s_addr=htons(INADDR_ANY);
 Так я поймаю любое подкбчение к IP хоста. Вот я и узаю один из них. Прописываю в опере и ничего, пишет срвер недоступен или подключается но сервер сообщений не передает. Вроде все правильно?
 
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| darkelf 
								Молодой специалист    Offline | 
								|  | « Ответ #5 : 05-05-2010 14:48 »  |  | 
 
 socketaddr.sin_addr.s_addr=htons(INADDR_ANY);
 лучше, наверное, без htons(). Прописываю в опере и ничего, пишет срвер недоступен или подключается но сервер сообщений не передает. Вроде все правильно?
 что Вы прописываете в Opere? Вообще, для тестирования серверов обычно используют telnet. |  
						| 
								|  |  
								| « Последнее редактирование: 05-05-2010 14:51 от darkelf » |  Записан | 
 |  |  | 
	| 
			| 
					
						| resource 
								Молодой специалист    Offline 
								Пол:    | 
								|  | « Ответ #6 : 05-05-2010 15:18 »  |  | 
 
 лучше, наверное, без htons().
 в случае INADDR_ANY - абсолютно  без разницы. Он всё равно нулю равен |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #7 : 05-05-2010 17:11 »  |  | 
 
 в случае INADDR_ANY - абсолютно  без разницы. Он всё равно нулю равен Да, все равно нулю и так и так. В опере писал IP, Telnet тоже использовал, пишет сбой подключения. IP ipconfig  видет такой же как и программа определяет, так что он правильный. |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| resource 
								Молодой специалист    Offline 
								Пол:    | 
								|  | « Ответ #8 : 05-05-2010 17:35 »  |  | 
 
 зачем функции socket() передаешь нуль вместо TCP протокола ? Эдак ты по IP конектишься (хотя так нельзя сказать про IP-протокол) а не по TCP
 ЗЫ это что принцип такой - не помню, что писать, напишу 0
 |  
						| 
								|  |  
								| « Последнее редактирование: 05-05-2010 17:37 от resource » |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #9 : 05-05-2010 19:02 »  |  | 
 
 Денисrf, будь внимателен!
 htons() => Host To Network, Short. Применяется для 16-битных величин. Таких как TCP или UDP порт. Обратное действие: ntohs().
 
 htonl() => Host To Network, Long. Применяется для 32-битных величин. Таких как IP-адрес. Обратная функция: ntohl().
 
 
 В протоколе можно указать 6 (TCP). По теории, должен использоваться TCP и при 0, но в винде все по особому и протокол указывать  надо.
 |  
						| 
								|  |  
								| « Последнее редактирование: 05-05-2010 19:07 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #10 : 07-05-2010 10:50 »  |  | 
 
 Я на TCP протокол так указываю - ServerSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #11 : 07-05-2010 11:29 »  |  | 
 
 И что в итоге?
 Кстати, браузером лучше в последнюю очередь тестировать - вдруг он через прокси пытается...
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #12 : 07-05-2010 13:27 »  |  | 
 
 Я пробую и через Telnet, и через Opera (на всякий).  Вообще адресную структуру вот так задаю:             socketaddr.sin_family=AF_INET;socketaddr.sin_port=htons(PORT_ADDR);
 socketaddr.sin_addr.s_addr=htonl ( INADDR_ANY );//htons(INADDR_ANY) - принимает подключения на все IP адреса
 
 //=====================Создание сокета==================================
 ServerSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 
И в результате обработка корректна. А вот интересный вопрос, а как широко применяются способы типа: 1) //Завязываем сообщения от сервера на сокет/*int Errors;
 const int WM_SERVER_ACCEPT = WM_USER+1;
 Errors=WSAAsyncSelect(ServerSocket,GetConsolHWND (),WM_SERVER_ACCEPT,FD_ACCEPT);
 if (Errors == SOCKET_ERROR)
 {
 printf(" AsyncSelect BAD\n");
 exit(1);
 }
 else printf("Good AsyncSelect \n");*/
 
2)  ////Создаем событие, првязываем к скету, определяем о чем ему сообщать//HANDLE hEventConect;// = WSA_INVALID_EVENT;
 //hEventConect = WSACreateEvent();
 //::WSAEventSelect(ServerSocket,hEventConect,FD_ACCEPT | FD_CLOSE);
 //// = (WSAEVENT*)::calloc(2, WSAEVENT);
 
 //WSAEVENT* pEvents;
 //pEvents= &hEventConect;												//INFINITE
 ////Сокет - одна переменная событий, НЕ ждать наступления всех событий, ждать 30с, НЕ получать алерты
 //Sleep(150);
 //
 //for (;;)
 //{
 //if (WSA_WAIT_FAILED!=::WSAWaitForMultipleEvents(1, &hEventConect, FALSE, 30, FALSE))
 //	{
 //	WSANETWORKEVENTS hConnectEvent;
 //	if (0==::WSAEnumNetworkEvents(ServerSocket,hEventConect,&hConnectEvent))
 //		{
 //		if (hConnectEvent.lNetworkEvents & FD_ACCEPT)
 //		{
 //		std::cout<<"Client connecting attempt"<<std::endl;
 //			if(hConnectEvent.lNetworkEvents & FD_CLOSE)
 //			{	//Если хост разорвал соединение
 //				WSACloseEvent(hEventConect); //Освобождаем ресурсы
 //				return 0; //Завершаем поток
 //			}
 //		}
 //		}
 //	}
 //}
 //=====================================================================================
Ведь это все тоже, верно? Конечно может не совсем корректный вопрос, все зависит от задач и плтформы сервера, но все же. Что по вашему мнению эффективнее? |  
						| 
								|  |  
								| « Последнее редактирование: 07-05-2010 13:29 от Денисrf » |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| resource 
								Молодой специалист    Offline 
								Пол:    | 
								|  | « Ответ #13 : 07-05-2010 14:31 »  |  | 
 
 WSAAsyncSelect  и вообще WSA* это, как я понимаю, относится исключительно к windows-сокетам. Впринципе вещь удобная. Не нужно вручную перебирать select'ом. Но сказать, что это лучше или хуже..... не могу (не знаю). |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #14 : 11-05-2010 13:30 »  |  | 
 
 Доброго времени всем! По ходу возникла еще одна ошибка. В этом модуле возникает ошибка нарушения прав доступа при попытке заполнить структуру  HOSTENT*    pClientHostent; для того, чтобы в последствии определить IP адрес клиента. while ((client_socket=accept(ServerSocket,(sockaddr *)&client_addr,&client_addr_size))){
 nclients++;
 HOSTENT*    pClientHostent;
 
 pClientHostent=gethostbyaddr((char *)client_addr.sin_addr.s_addr,4,AF_INET); ----Эта строка вызывает ошибку!!!
 
 std::cout<<"New conect! Users online: ";
 std::cout<<nclients<<std::endl;
 DWORD thID;
 if (CreateThread(NULL,NULL,SexToClient,&client_socket,NULL,&thID))
 std::cout<<"New user in new thread... Thread's descriptor: "<<thID<<std::endl;
 
 
 }
Ошибка не при компиляции, а при выполнении программы при подключении клиента. Необработанное исключение в "0x71a9e3e1" в "Socket_Server.exe": 0xC0000005: Нарушение прав доступа при чтении "0xf98ae90a". Какие ваши мысли? |  
						| 
								|  |  
								| « Последнее редактирование: 11-05-2010 13:36 от Вад » |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| Вад | 
								|  | « Ответ #15 : 11-05-2010 13:40 »  |  | 
 
 А кто сказал, что структура sockaddr содержит  char* - указатель на строку с адресом хоста? Там только ulong. Его нельзя так приводить. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #16 : 11-05-2010 16:23 »  |  | 
 
 А точно так я не внимателен. Спасибо. Вот как решил: HOSTENT*    pClientHostent;pClientHostent=gethostbyaddr((char *)inet_ntoa(client_addr.sin_addr),4,AF_INET);
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #17 : 11-05-2010 16:34 »  |  | 
 
 Функция inet_ntoa() не безопасна в многопоточной программе, т.к. возвращает указатель на статический внутренний буфер. Надо помнить об этом и использовать осторожно. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #18 : 11-05-2010 17:02 »  |  | 
 
 Как это может повлиять на многопотчную программу? Будет не правильно IP адрес последующих клиентов определяться? Ну не обнулять же структуру каждый раз. |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #19 : 11-05-2010 17:44 »  |  | 
 
 Денисrf, буфер у inet_ntoa() всего один на процесс. Представь себе, что один поток вызвал эту функцию со своими параметрами и получил адрес статического буфера, но пока он не не закончил обработку буфера другой поток тоже делает вызов этой функции и буфер перезаписывается. Не трудно догадаться, что для программы это — нештатная ситуация. Первая ошибка новичков в многопоточном программировании — игнорирование подобных ситуаций (типа, вероятность мала — авось пронесет). |  
						| 
								|  |  
								| « Последнее редактирование: 11-05-2010 17:46 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #20 : 11-05-2010 18:12 »  |  | 
 
 Буфер один на процесс, что же при порождении второго потока, или при повторном вызове он не перезаписывается? Это вообще действительно такая критичная ошибка? |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #21 : 11-05-2010 18:18 »  |  | 
 
 Денисrf, вот тебе пример: char * some_func(int val){
 static char buffer[32];
 
 buffer[snprintf(buffer, 31, "%d", val)] = 0;
 return buffer;
 }
 
Подумай на досуге о подводных камнях такого подхода. За одно ответишь на свои вопросы. Функция inet_ntoa очень старая и тогда о многопоточности не задумывались. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Денисrf | 
								|  | « Ответ #22 :  12-05-2010 05:32 »   |  | 
 
 Спасибо за примерчик )) обязательно проанализирую. |  
						| 
								|  |  
								|  |  Записан | 
 
 Your password is personal - do not share it with anyone and make sure it is not easy to crack. |  |  | 
	|  |