написал socks5 сервак: Code: #pragma comment(linker, "/MERGE:.data=.text") #pragma comment(linker, "/MERGE:.rdata=.text") #pragma comment(linker, "/SECTION:.text,EWR") #include <WinSock2.h> #include <Windows.h> struct auths5{ BYTE ver;//версия BYTE nMethods;//кол-во методов }; struct auth_resp { BYTE ver;//версия BYTE method;//выбранный метод }; struct s5request{ BYTE Version; // 5 BYTE Cmd ; // 1 - CONNECT BYTE Reserved; // 0 BYTE AType; // 1 - IPv4; 3 - domain name; 4 - IPv6 }; struct resp{ BYTE Version; // 5 BYTE Rep ; // 0 - Ok BYTE Reserved; // 0 BYTE AType; // 1 - IPv4; 3 - domain name; 4 - IPv6 }; void portmapper(SOCKET client,SOCKET target) { int len; char buf[1024]; fd_set fd; while(TRUE){ FD_ZERO(&fd); FD_SET(client, &fd); FD_SET(target, &fd); for(int i=0;i<1024;i++) buf[i]=0; select(0, &fd, NULL, NULL, NULL); if(FD_ISSET(client, &fd)){//если прислал данные клиент //перешлем от одного другому if((len = recv(client,buf,sizeof(buf),0))== -1){ break; } if(send(target,buf,len,0)== -1){ break; } } if(FD_ISSET(target,&fd)){//если прислал данные сервер //перешлем от одного другому if((len = recv(target,buf,sizeof(buf),0))== -1){ break; } if(send(client,buf,len,0)== -1){ break; } } } //чистим за собой closesocket(client); closesocket(target); } DWORD __stdcall ClientRoute(void *params) { SOCKET as= *(SOCKET *)params; if(as==INVALID_SOCKET) return -1;//продолжаем прием если ошибка auths5 req;//структура авторизации recv(as,(char *)&req,sizeof(req),0);//принимаем BYTE *methods=(BYTE *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,req.nMethods);//инициализируем массив методов авторизации, поддерживаемых клиентом for(int i=0;i<req.nMethods;i++) methods[i]=0; recv(as,(char *)methods,req.nMethods,0);//получаем методы авторизации auth_resp r;//заполняем ответ r.ver=5;//5-я версия r.method=0;//авторизация не нужна send(as,(char *)&r,sizeof(r),0);//посылаем ответ s5request s5r;//запрос recv(as,(char *)&s5r,sizeof(s5r),0);//получаем запрос //printf("ver: %d, cmd: %d,reserved: %d,atype: %d\n",s5r.Version,s5r.Cmd,s5r.Reserved,s5r.AType);//выводим полученный запрос if(s5r.Cmd==1)//если команда connect { if(s5r.AType==1)//если IpV4 { DWORD addr=0;//адрес recv(as,(char *)&addr,sizeof(DWORD),0); WORD port=0;//порт recv(as,(char *)&port,sizeof(WORD),0); sockaddr_in caddr;//заполняем адресную структуру caddr.sin_addr.S_un.S_addr=addr; caddr.sin_family=AF_INET; caddr.sin_port=port; SOCKET ss=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//создание сокета if(connect(ss,(sockaddr *)&caddr,sizeof(caddr))==0)//коннектимся { resp rsp; rsp.AType=1; rsp.Rep=0;//успешно rsp.Reserved=0; rsp.Version=5; send(as,(char *)&rsp,sizeof(rsp),0);//заголовок send(as,(char *)&caddr.sin_addr.S_un.S_addr,sizeof(DWORD),0);//адрес send(as,(char *)&caddr.sin_port,sizeof(WORD),0);//порт portmapper(as,ss);//зарускаем обмен данными } } if(s5r.AType==3)//если доменное имя { BYTE alen=0; recv(as,(char *)&alen,sizeof(BYTE),0);//получаем длину доменного имени char *domain=(char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,alen);//выделяем память нужного размера domain[alen]='\0'; recv(as,domain,alen,0);//получаем доменное имя WORD aport=0;//порт recv(as,(char *)&aport,sizeof(WORD),0); hostent *hst=gethostbyname(domain); char *addr=inet_ntoa(*(in_addr *)(*(hst->h_addr_list))); sockaddr_in caddr;//заполняем адресную структуру caddr.sin_addr.S_un.S_addr=inet_addr(addr); caddr.sin_family=AF_INET; caddr.sin_port=aport; SOCKET ss=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//создание сокета if(connect(ss,(sockaddr *)&caddr,sizeof(caddr))==0)//коннектимся { resp rsp; rsp.AType=1; rsp.Rep=0;//успешно rsp.Reserved=0; rsp.Version=5; send(as,(char *)&rsp,sizeof(rsp),0);//заголовок send(as,(char *)&caddr.sin_addr.S_un.S_addr,sizeof(DWORD),0);//адрес send(as,(char *)&caddr.sin_port,sizeof(WORD),0);//порт portmapper(as,ss);//зарускаем обмен данными } } } return 0; } DWORD __stdcall socks5_listen(LPVOID param) { SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//создаем сокет if(s==INVALID_SOCKET) return -1;//если не создался сокет выходим //заполняем адресную структуру sockaddr_in sa; sa.sin_addr.S_un.S_addr=INADDR_ANY; sa.sin_port=htons(1080); sa.sin_family=AF_INET; if(bind(s,(sockaddr *)&sa,sizeof(sa))==(-1)) return -1;//выходим если ошибка if(listen(s,5)==(-1)) return -1;//выходим если ошибка while(true)//прием соединений { sockaddr_in saa;//адресная структура для принятого соединения SOCKET as=accept(s,(sockaddr *)&saa,NULL);//прием //создаем отдельный поток для каждого соединения DWORD id=0; CreateThread(NULL,0,ClientRoute,&as,0,&id); } return 0; } void entry()//энтрипойнт { /*инит сокетов*/ WSAData w; if(WSAStartup(MAKEWORD(2,2),&w)!=0) ExitProcess(0);//в случае неудачного инита выходим DWORD dwid; HANDLE hThread=CreateThread(NULL,0,socks5_listen,NULL,0,&dwid);//асинхронно стратуем прослушку WaitForSingleObject(hThread,INFINITE); ExitProcess(0); } полностью отказался от c crt, но почемуто у меня вылазит ошибка Ошибка 3 error LNK2001: неразрешенный внешний символ "_memset" c:\Users\vova\documents\visual studio 2010\Projects\socks5\socks5\socks_serv.obj socks5 хотя memset там не использую...
так все ок когда писал консолку по шаблону. опера и аську пахала просто за*бись. а когда решил перевести на windows и убрать все лишее по статье как писал slesh - вот такая херня
Генерируем ассемблерный листинг, видим, что компилятор использует memset при оптимизации твоего цикла: PHP: for(int i=0;i<1024;i++) buf[i]=0; Берем и оптимизируем его сами: PHP: for(int i=0;i<1024/4;i++) ((long*)&buf[0])[i]=0; memset из листинга исчезает. У меня был еще символ _crt_debugger_hook, от него я избавился, выключив опцию Buffer Security Check в настройках компилятора. Код кстати трешовый, Си и Си++ вместе, а еще память освобождать забываешь за собой.
А после этого приема компилятор выкидывает предупреждение. warning C4789: конечная область для копирования памяти слишком мала А как некоторые функции подключить в проект из crt. Я там нашел memset.c, но как правильно ее в проект подключить через инклуды.
Почему, это довольно-таки удобная штука. Если мало кода и не нравится, что exe файл большой получается, компилируй с /MD свичом, приложение слинкуется с crt, который в dll'е. Err, незаметил дату создания первого поста.
Надо линковать с msvcrt.lib из WinDDK, msvcrt.dll есть на каждом Win, от 98 до 10. Есть некоторые ограничения (filesize < 2GB, нет C++, нет %lld, %llx), но в большинстве случаев это некритично. Кстати MinGW так и делает (линкует с msvcrt.dll), можно на нём собирать а не на MSVC.
ну я хз как нужно писать чтоб хватило одного лишь msvcrt.dll если пишешь на человеческом С++ то тянутся еще msvcp.dll, vccorlib.dll, vcruntime.dll, а их по дефолту нету.