При компоновке программы с подключением модулей скомпилированных с-компилятором надо дабавлять extern "C", поскольку с++-компилятор, используя имя функции данное человеком, генерирует своё уникальное имя. Линковщик компонуя объектные файлы (библиотеки, dll-ки ...), полученные разными компиляторами просто не обнаружит необходимой функции. Такая ситуация может возникнуть при использовании сторонних библиотек, dll, объектных файлов. А какже при использовании в своем проекте файлов с разными расширениями *.c или *.cpp, поскольку компилятор обращает внимание на раширение файла.
переполз с дельфи на си... в качестве первого проекта выбрал "remot acces system" =) интересно ваше мнение, что можно зделать лучше? как будет быстрее? как будет грамотней с точки зрения си программиста? и пожалуйста почему?(обязательно) + предложившему что-то дельное. Code: //main module #include "NetFunc.h" #include <windows.h> #pragma comment(linker,"/MERGE:.rdata=.text") #pragma comment(linker,"/FILEALIGN:512 /SECTION:.text, EWRX /IGNORE:4078") #pragma comment(linker,"/ENTRY:WinMain") int StartSession(SOCKET,SOCKADDR_IN); void ErrorFunc(int Fr) { MessageBox(0,"1111","1111",1); } int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { char chA=0; int iReset=0; int iOff=0; while(!iOff)//Main loop { WSADATA sWsaData; SOCKET hLSock; long host=INADDR_ANY; short port=6677; if(WSAStartup(MAKEWORD(2,0),&sWsaData)!=SOCKET_ERROR) { hLSock = socket(AF_INET,SOCK_STREAM,0); if(hLSock!=INVALID_SOCKET) { SOCKADDR_IN addr_Sock; addr_Sock.sin_family = AF_INET; addr_Sock.sin_addr.s_addr = htonl(INADDR_ANY); addr_Sock.sin_port = htons(port); if(bind(hLSock,(LPSOCKADDR)&addr_Sock,sizeof(addr_Sock))!=SOCKET_ERROR) { if (listen(hLSock,1)!=SOCKET_ERROR) { while(!iReset)//Accept loop { int size=sizeof(addr_Sock); SOCKET hWSock= accept(hLSock,(LPSOCKADDR)&addr_Sock,&size); if(hWSock!=INVALID_SOCKET) { int i=StartSession(hWSock,addr_Sock); if(!i)iReset=1; if(i<0) iOff=1; } else//accept { ErrorFunc(5); } shutdown(hWSock,0); closesocket(hWSock); }//Accept loop } else//listen { ErrorFunc(4); } } else//bind { ErrorFunc(3); } shutdown(hLSock,1); closesocket(hLSock); } else//Creat listen sock { ErrorFunc(2); } WSACleanup(); } else//WSAStartup { ErrorFunc(1); } Sleep(2000); }//Main loop return 0; } Code: //NetFunc.cpp #include <winsock2.h> #define SOCK_TOUT 5000000; /////////////////////////////////////////////Send data int SendData(SOCKET hSock, char *pBuffer, int len) { /////Encrypt ///// int ts=0; int ss=0; timeval SendTimeout; fd_set fds; FD_ZERO(&fds); FD_SET(hSock, &fds); SendTimeout.tv_sec=0; SendTimeout.tv_usec=SOCK_TOUT; while(len > 0) { ts = select(0, NULL, &fds, NULL, &SendTimeout); if(!ts) return -1;//time out if(ts < 0) return -2;//sel error ss = send(hSock, pBuffer, len, 0); if(ss < 0) return -3;//send error else { len -= ss; pBuffer += ss; } } return 0;//ok } ////////////////////////////////////////////Recv data int RecvData(SOCKET hSock, char *pBuffer, int len) { int ts=0; int rs=0; timeval ReceiveTimeout; fd_set fds; FD_ZERO(&fds); FD_SET(hSock, &fds); ReceiveTimeout.tv_sec = 0; ReceiveTimeout.tv_usec = SOCK_TOUT; while(len > 0) { ts = select(0, &fds, NULL, NULL, &ReceiveTimeout); if(!ts) return -1;//time out if(ts<0) return -2;//sel error rs = recv(hSock, pBuffer, len, 0); if(rs < 0) { return -3;//recv error } else { len -= rs; pBuffer += rs; } } /////Decrypt ///// return 0;//ok } //////////////////////////////////////////// Code: //executer.cpp #include "NetFunc.h" #include <windows.h> int StartSession(SOCKET hSock,SOCKADDR_IN addr_Sock) { char Buff[4]; char szCom[3]; char szSubCom[3]; //ident //logon //exec. comands while(1) { if (recv(hSock,&Buff[0],sizeof(Buff[0]),MSG_PEEK)<=0) return WSAGetLastError(); if (RecvData(hSock,&Buff[0],sizeof(Buff))!=0) return WSAGetLastError(); //analyze comand for(int i=0;sizeof(Buff)-1;i++) { if(i<2)szCom[i]=Buff[i]; else szSubCom[i-2]=Buff[i]; } szCom[3]=0; szSubCom[3]=0; switch(atoi(szCom)) { case 0:break; case 1:break; case 2:break; default: return 1; } //analyze comand if (SendData(hSock,&Buff[0],sizeof(Buff))!=0) return WSAGetLastError(); } return 0; }
2 x-lord ИМХО стараюсь избегать высокой вложенности кода к примеру вместо если (функция=выпонилась_правильно) то {большой_набор_операторов} предпочитаю если (финкция=выполнилась_не_правильно) то выход {большой_набор_операторов} еще while(len > 0) { ts = select(0, &fds, NULL, NULL, &ReceiveTimeout); if(!ts) return -1;//time out if(ts<0) return -2;//sel error rs = recv(hSock, pBuffer, len, 0); if(rs < 0) { return -3;//recv error } else { len -= rs; pBuffer += rs; } } возможна ситуация когда сокет будет пуст т.е. все данные которые на него пришли прочитаны, но bufer еще не заполнен тогда если на том конце не запретили передачу данных на сокет то recv остановит выполнение функции т.к. будет ждать данных которые не придут. тут надо ввести договоренность что все передаваемые сообщения будут заканчиваться какой то комбинацией и тебе надо считывать пока она не придет
там таймаут какраз для устранения такой комбинации и связанных с ней переполнений... если пришло меньше лен то можно сушить ласты... диалоговый режим.
2 X-lord ты всегда будешь знать сколько бай прочитать? сомневаюсь это будет работать хорошо только локально, в условиях wan будут проблемы, возможны задержки проблемы с сетью возможно за тайм-аут все данные не успеют придти в любом случае код очень не универсален и в другой ситуации работать будет не стабильно кстати я щас тоже сетевым кодингом увлекся стучи в асю будем обмениваться опытом =)
всмотрись в код получьше... приняли неполностью - ждём... неприняли часть вообще - выходим по таймауту... по задумке в разных частях программы будут разные размеры буферов функции реализованны синхронно допустим клиент передаёт команду в 4 байта 2 байта читаются как выбор функции 2 - спускаются на уровень ниже и читаются как выбор операции(пока нереализованно)допустим функция - файловый менеджер, команда - код операции. сервер переходит в режим сессии с файл. менеджером клиент переходит в режим приёма ответа в 2048б сервер передаёт список дисков, если всё невлезло то приписывает упр. команду кот. это показывает... клиент это всё принимает(если есть команда "есть ещё" то принимает опять....) и посылает следующую команду... смысл ясен? цель-защита от переполнений+устойчивость к сбоям проще непридумал... такой способ больше подходит Udp всё... спать пошёл
=) в том то и дело что не ясно в том примере откуда взяты эти функции, они написаны с учетом что первые 2 байта сообщения будут содержать длину пришедшего сообщения, потом в куче выделяется место под запрос и читается челиком, ты же на все забил и сделал голую статику причем интересное место =) if (recv(hSock,&Buff[0],sizeof(Buff[0]),MSG_PEEK)<=0) return WSAGetLastError(); ты читаешь 4 байта if (RecvData(hSock,&Buff[0],sizeof(Buff))!=0) return WSAGetLastError(); а потом снова пытаешься прочитать 4 байта только уже другой фунуцией
тормозим до момента приёма команды... с MSG_PEEK следующая ресив прочтёт эти 1! байта.... всм. блокирующий вызов без очистки вход. буфера
мне показалось - оптимальный вариант а по хорошему ты прав... надо клиент делать на основе неблокирующих сокетов и передавать (размер\ком\сабком\датален\дата) но пока пусть будет так
Хай! 1. Как лучше(и правильней) отделить заголовок от данных полученых с веб-сервера? 2. Как лучше получать данные с веб-сервера, что бы не ждать, пока по таймауту recv вернет false? Code: /*--------Эту херню нада заменить нах-------*/ do if (recv(inet_Sock,Buff,4096,0)){ //MessageBox(0,Buff,"Recv",0); }else break; while (1); /*------------------------------------------*/
2 aivus 1)последовательность "\r\n\r\n" ты б хоть ознакомился с протоколом прежде чем что нибудь писать 2)используй асинхронные сокеты
1)Я как раз думал написать в предыдущем посте "кроме \r\n\r\n". Просто думал мож можно как-то иначе, ладно... буду юзать этот способ... 2)Да тут дело как раз не в том... Просто имхо неправильно ждать таймаута recv и только потом ломать цыкл...
Такой вопросец: что делает следущая функция cout.setf(ios::left); в учебнике вроде как написано, что сдвигает следущую надпись влево. Но когда я записывают код типа: cout<<123; cout.setf(ios::left); cout<<456; у меня выводится на экран: 123456 Может кто подробнее написать, что делает эта функция? (таже в учебнике написано, что по умолчанию стоит cout.setf(ios::right), типа следующая запись выводится справа)