Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.14.84] |
|
Сообщ.
#1
,
|
|
|
Товарищи!
Позарез нужно срочно написать нечто в духе Telnet. Подскажите как это делать? Надо чтобы сервер подрубарся к заданному порту (число из командной строки) и ждал подключения клиента. Если тот подключился к тому же порту, то выдавать ему приветствие и ждать от него команд, при получении команды от клиента (строка), что-то с ней делать и отсылать обратно (строку). КАК ЭТО СОТВОРИТЬ? ГДЕ ПРО ЭТО ПОЧИТАТЬ? Может кто-нибудь исходники накидать, чтобы разобраться? Видел в одном месте кое-что но там это под Linux, а мне надо под Винды. Может кто шарит, скажите как доработать это: #include "stdafx.h" #include <stdio.h> #include <conio.h> #include <winsock2.h> #include <protocol.h> #define MAX_PACKET_SIZE 0x10000 #define SIO_RCVALL 0x98000001 static char Buffer[MAX_PACKET_SIZE]; int main(int argc, char* argv[]) { WSADATA wsadata; // Инициализация WinSock. SOCKET s; // Cлущающий сокет. char name[128]; // Имя хоста (компьютера). HOSTENT* phe; // Информация о хосте. SOCKADDR_IN sa; // Адрес хоста unsigned long flag = 1; // Флаг PROMISC Вкл/выкл. // инициализация WSAStartup(MAKEWORD(2,2), &wsadata); s = socket( AF_INET, SOCK_RAW, IPPROTO_IP ); gethostname(name, sizeof(name)); phe = gethostbyname( name ); ZeroMemory( &sa, sizeof(sa) ); sa.sin_family = AF_INET; sa.sin_addr.s_addr = ((struct in_addr *)phe->h_addr_list[0])->s_addr; bind(s, (SOCKADDR *)&sa, sizeof(SOCKADDR)); // Включение promiscuous mode. ioctlsocket(s, SIO_RCVALL, &flag); long cnt = 0; // Приём IP-пакетов. while( !_kbhit() ) { int count; printf("%d", cnt++); count = recv( s, Buffer, sizeof(Buffer), 0 ); // обработка IP-пакета if( count >= sizeof(IP_HEADER) ) { IP_HEADER* hdr = (IP_HEADER *)Buffer; //что-то делаем с пакетом... } } // Конец работы. closesocket( s ); WSACleanup(); return 0; } Как привести этот сервер в нужный вид и дописать к нему клиент |
Сообщ.
#2
,
|
|
|
А нужно чтоб много клиентов могли к серверу подключится одновременно???
Добавлено Если да то вот так можно: Server : #include <stdio.h> #include <string.h> #include <winsock2.h> #include <conio.h> #pragma comment(lib, "ws2_32.lib") #define PORT 31337 SOCKADDR_IN socketaddr; SOCKET sock; const int WM_SERVER_ACCEPT = WM_USER+1; int nclients = 0; DWORD WINAPI SexToClient(LPVOID client_socket); bool _startserver(); HWND GetConsoleHWND(); int main() { _startserver(); return 0; } bool _startserver() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData)) { printf ("Winsock not bi initialized !\n"); WSACleanup(); return false; } if ((sock=socket(AF_INET,SOCK_STREAM,0))<0) { printf("Error socket %d\n",WSAGetLastError()); WSACleanup(); return false; } sockaddr_in local_addr; local_addr.sin_family=AF_INET; local_addr.sin_port=htons(31337); local_addr.sin_addr.s_addr=INADDR_ANY; if (bind(sock,(struct sockaddr *)&local_addr,sizeof(local_addr))==SOCKET_ERROR) { printf("Error bind %d\n",WSAGetLastError()); closesocket(sock); WSACleanup(); return false; } if (listen(sock, 0x100)) { printf("Error listen %d\n",WSAGetLastError()); closesocket(sock); WSACleanup(); return false; } printf("Waiting for connections...\n"); int len=sizeof(local_addr); SOCKET client_socket; // сокет для клиента sockaddr_in client_addr; // адрес клиента (заполняется системой) int client_addr_size=sizeof(client_addr); while((client_socket=accept(sock, (sockaddr *)&client_addr, &client_addr_size))) { nclients++; // увеличиваем счетчик подключившихся клиентов // пытаемся получить имя хоста HOSTENT *hst; hst=gethostbyaddr((char *)&client_addr.sin_addr.s_addr,4,AF_INET); // вывод сведений о клиенте printf("+%s [%s] new connect!\n", (hst)?hst->h_name:"",inet_ntoa(client_addr.sin_addr)); printf("NEWS USER\n"); //printf("ncl inf: = %l",client_socket[nclients]); //////////////////////////////////////////////// //////////////////////////////////////////////// // Вызов нового потока для обслужвания клиента // Да, для этого рекомендуется использовать _beginthreadex // но, поскольку никаких вызов функций стандартной Си библиотеки // поток не делает, можно обойтись и CreateThread DWORD thID; CreateThread(NULL,NULL,SexToClient,&client_socket,NULL,&thID); /////////////////////////////////////////////// /////////////////////////////////////////////// } return true; } HWND GetConsoleHWND() { SetConsoleTitle("Sarver started..."); HWND hwndConsoleWindow; hwndConsoleWindow=FindWindow(NULL, "Sarver started..."); if (hwndConsoleWindow==0) { printf("Error Find Window"); exit(0); } return hwndConsoleWindow; } // Эта функция создается в отдельном потоке // и обсуживает очередного подключившегося клиента независимо от остальных DWORD WINAPI SexToClient(LPVOID client_socket) { SOCKET my_sock; my_sock=((SOCKET *) client_socket)[0]; char buff[9999]; #define sHELLO "Hello, Sailor\r\n" // отправляем клиенту приветствие send(my_sock,sHELLO,sizeof(sHELLO),0); // цикл эхо-сервера: прием строки от клиента и возвращение ее клиенту while(int recvbyte = recv(my_sock,buff,sizeof(buff),0)) { //главный цикл обработки сообщений от клиентов... if(recvbyte<=0) { break; } printf("Client=> %s",buff); send(my_sock,buff,strlen(buff),0); buff[0]=0; } // если мы здесь, то произошел выход из цикла по причине // возращения функцией recv ошибки – соединение с клиентом разорвано nclients--; // уменьшаем счетчик активных клиентов printf("-disconnect\n"); // закрываем сокет closesocket(my_sock); return 0; } Client #include <stdio.h> #include <string.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") #define PORT 31337 char* HOST="127.0.0.1"; SOCKADDR_IN socketaddr; SOCKET sock; bool _connect(char* addres); bool _getdata(); int main(int argc, char* pszArgs[]) { if(argc>1) { HOST=pszArgs[1]; } if(_connect(HOST)) _getdata(); scanf("A"); return 0; } bool _connect(char* addres) { WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData)) { printf ("Winsock not bi initialized !\n"); WSACleanup(); return false; } sock = socket(AF_INET,SOCK_STREAM,0); socketaddr.sin_family = AF_INET; socketaddr.sin_addr.s_addr=inet_addr(addres); socketaddr.sin_port=htons(PORT); if(connect(sock,(sockaddr *)&socketaddr,sizeof(socketaddr))) { printf("Can\'t connect to %s\n\n",addres); WSACleanup(); return false; } else printf("Connected!\n\n\n\n"); return true; } bool _getdata() { char buff[1024]; int nsize; while((nsize=recv(sock,buff,sizeof(buff),0))!=SOCKET_ERROR) { // ставим завершающий ноль в конце строки //buff[nsize]=0; // выводим на экран buff[nsize]='\0'; printf("Server => %s\n",buff); // читаем пользовательский ввод с клавиатуры printf("=> "); fgets(buff,sizeof(buff),stdin); // проверка на "quit" if (!strcmp(&buff[0],"quit\n")) { // Корректный выход printf("Exit..."); closesocket(sock); WSACleanup(); return true; } //шлем дату... send(sock,buff,sizeof(buff),0); } return true; } Сервер слушает порт 31337 на подключение клиентов... |
Сообщ.
#3
,
|
|
|
Спасибо.
А если клиент может подрубаться только один? Какой кусок кода измениться? |
Сообщ.
#4
,
|
|
|
2 YOG:
тот код, что ты привел - это код сниффера(программа которая перехватывает пакеты), в твоем случае она будет перехватывать весь трафик...доработать не получится, надо переделывать полностью... |
Сообщ.
#5
,
|
|
|
Цитата А если клиент может подрубаться только один? Какой кусок кода измениться? У меня нет, сколько хочешь.... Добавлено Ну а так подключение нового клиента обрабатывает ф-ия accept |
Сообщ.
#6
,
|
|
|
M YOG, Используем тег [code] для добавления текста программы в пост! Устное предупреждение! Читаем правила! Jenizix, если слишком длинный код, то лучше выкладывать исходник, а не постить в теге [CODE]. |
Сообщ.
#7
,
|
|
|
send(my_sock,sHELLO,sizeof(sHELLO),0); // Тут конечно можно написать третьим параметром sizeof(sHELLO) // т.к. #define sHELLO "Hello, Sailor\r\n" send(sock,buff,sizeof(buff),0); // А вот тут советую поменять sizeof() на strlen() ибо char buff[9999]; |
Сообщ.
#8
,
|
|
|
Может у кого нить есть сервер и клиент не в консольном варианте, а в диалоговом (хотябы )с примитивным набором функций. Нормально произвести коннект, и возможность отправлять мессаги типа - HelloWorld в обе стороны ессесно.
Если есть, то уже очень хотелось бы посмотреть на него! |