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


Автор: YOG 12.04.05, 08:50
Товарищи!
Позарез нужно срочно написать нечто в духе Telnet.
Подскажите как это делать?

Надо чтобы сервер подрубарся к заданному порту (число из командной строки) и ждал подключения клиента. Если тот подключился к тому же порту, то выдавать ему приветствие и ждать от него команд, при получении команды от клиента (строка), что-то с ней делать и отсылать обратно (строку).

КАК ЭТО СОТВОРИТЬ? ГДЕ ПРО ЭТО ПОЧИТАТЬ?

Может кто-нибудь исходники накидать, чтобы разобраться?

Видел в одном месте кое-что но там это под Linux, а мне надо под Винды.


Может кто шарит, скажите как доработать это:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #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;
    }

Как привести этот сервер в нужный вид и дописать к нему клиент

Автор: Jenizix 12.04.05, 08:57
А нужно чтоб много клиентов могли к серверу подключится одновременно???

Добавлено
Если да то вот так можно:

Server :
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #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
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #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 на подключение клиентов...

Автор: YOG 12.04.05, 09:29
Спасибо.
А если клиент может подрубаться только один? Какой кусок кода измениться?

Автор: Dr_ShpitsVogel 12.04.05, 09:33
2 YOG:
тот код, что ты привел - это код сниффера(программа которая перехватывает пакеты), в твоем случае она будет перехватывать весь трафик...доработать не получится, надо переделывать полностью...

Автор: Jenizix 12.04.05, 09:50
Цитата
А если клиент может подрубаться только один? Какой кусок кода измениться?

У меня нет, сколько хочешь....

Добавлено
Ну а так подключение нового клиента обрабатывает ф-ия accept

Автор: ViGOur 12.04.05, 11:02
M
YOG, Используем тег [code] для добавления текста программы в пост! Устное предупреждение! Читаем правила!

Jenizix, если слишком длинный код, то лучше выкладывать исходник, а не постить в теге [CODE].  ;)

Автор: MOHAX 12.04.05, 18:02
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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];

Автор: madman 12.04.05, 18:13
Может у кого нить есть сервер и клиент не в консольном варианте, а в диалоговом (хотябы :))с примитивным набором функций. Нормально произвести коннект, и возможность отправлять мессаги типа - HelloWorld :D в обе стороны ессесно.
Если есть, то уже очень хотелось бы посмотреть на него!

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