добрый день! у меня такая проблема: пишу клиент-сервер(радмин). клиент на дельфе, сервер на с++. работает по бинарному протоколу: сначала заголовок: Code: struct header{ DWORD sing;//сингапура, подтверждающая что это нужный пакет DWORD command;//номер команды DWORD seq;//id команды(номер пакета). ответ на нее отправляется с таким же id DWORD datalen;// длинна данных посылаемых после заголовка(например скриншот, имя пользователя компа или имя директории которую нужно просмотреть) }; //константы такие пока только: #define SIGN 0x007754 #define CS_HELLO 0x001 #define SC_HELLO_ACK 0x0010 вот код сервера: Code: #ifndef UNICODE #define UNICODE #endif #include <winsock2.h> #include <stdio.h> #include <windows.h> #include "proto.h" // Need to link with Ws2_32.lib #pragma comment(lib, "Ws2_32.lib") int wmain(void) { //---------------------- // Initialize Winsock. WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != NO_ERROR) { wprintf(L"WSAStartup failed with error: %ld\n", iResult); return 1; } //---------------------- // Create a SOCKET for listening for // incoming connection requests. SOCKET ListenSocket; ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ListenSocket == INVALID_SOCKET) { wprintf(L"socket failed with error: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } //---------------------- // The sockaddr_in structure specifies the address family, // IP address, and port for the socket that is being bound. sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr("127.0.0.1"); service.sin_port = htons(27015); if (bind(ListenSocket, (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) { wprintf(L"bind failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } //---------------------- // Listen for incoming connection requests. // on the created socket if (listen(ListenSocket, 1) == SOCKET_ERROR) { wprintf(L"listen failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } //---------------------- // Create a SOCKET for accepting incoming requests. SOCKET AcceptSocket; wprintf(L"Waiting for client to connect...\n"); //---------------------- // Accept the connection. AcceptSocket = accept(ListenSocket, NULL, NULL); if (AcceptSocket == INVALID_SOCKET) { wprintf(L"accept failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } else wprintf(L"Client connected.\n"); header pack; ZeroMemory((LPVOID)&pack,sizeof(pack)); while(true) { int lResult=0; lResult=recv(ListenSocket,(char *)&pack,sizeof(pack),0); if(lResult==0) continue; else { printf("seq: %d cmd: %d",pack.seq,pack.command); pack.command=SC_HELLO_ACK; send(ListenSocket,(char *)&pack,sizeof(pack),0); wprintf(L"cmd sended..."); // No longer need server socket closesocket(ListenSocket); getchar(); break; } } WSACleanup(); return 0; } вот код клиента: Code: unit main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Sockets, StdCtrls,winsock,proto; type Tmainfrm = class(TForm) ConnBtn: TButton; hostedit: TEdit; portedit: TEdit; procedure ConnBtnClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var mainfrm: Tmainfrm; implementation {$R *.dfm} function pack(cmd,seq,dlen:DWORD):header; begin result.sing:=SIGN; result.command:=cmd; result.seq:=seq; result.datalen:=dlen; end; Function LookupName(name:String): TInAddr; var HostEnt: PHostEnt; InAddr: TInAddr; begin HostEnt := gethostbyname(PChar(name)); FillChar(InAddr, SizeOf(InAddr), 0); if HostEnt <> nil then begin with InAddr, HostEnt^ do begin S_un_b.s_b1 := h_addr^[0]; S_un_b.s_b2 := h_addr^[1]; S_un_b.s_b3 := h_addr^[2]; S_un_b.s_b4 := h_addr^[3]; end; end; Result := InAddr; end; procedure Tmainfrm.ConnBtnClick(Sender: TObject); var WD:WSAData; sock:THandle; sa:SockAddr_IN; data:header; begin If WSAStartup(MakeWord(2,2),WD)<>0 then begin MessageBox(mainfrm.Handle,'Initialization failed!','Error',MB_OK or MB_ICONERROR); exit; end; sock:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if sock=INVALID_HANDLE_VALUE then begin MessageBox(mainfrm.Handle,'winsock socket() failed!','Error',MB_OK or MB_ICONERROR); exit; end; sa.sin_family:=AF_INET; sa.sin_port:=htons(StrToInt(portedit.Text)); sa.sin_addr:=lookupname(pchar(hostedit.Text)); if connect(sock,sa,sizeof(sa))<>0 then begin MessageBox(mainfrm.Handle,'connection failed!','Error',MB_OK or MB_ICONERROR); exit; end; data:=pack(CS_HELLO,1,0); send(sock,data,sizeof(data),0); ZeroMemory(@data,sizeof(data)); recv(sock,data,sizeof(data),0); if (data.command=SC_HELLO_ACK)and(data.sing=SIGN)and(data.seq=0) then begin showmessage('ok! command hello_ack recived!'); CLoseSocket(sock); WsaCleanUP(); end; end; end. дело в том что на сервер ничего не приходит. когда послыаю заголовок из клиента - сниффер показывает его как надо, но когда ставлю снифер на сервер - на сокет не приходит не чего, хотя там стоит проверка: Code: int lResult=0; lResult=recv(ListenSocket,(char *)&pack,sizeof(pack),0); if(lResult==0) continue; else { printf("seq: %d cmd: %d",pack.seq,pack.command); pack.command=SC_HELLO_ACK; send(ListenSocket,(char *)&pack,sizeof(pack),0); wprintf(L"cmd sended..."); // No longer need server socket closesocket(ListenSocket); getchar(); break; } подскажите, как решить такую проблему?
да. в эдит вввожу 27015-й порт и хост 127.0.0.1 пишет что приконнектился, сокет создался(в сниффере видно), а данных нет
вот код сервера: Code: ........... AcceptSocket = accept(ListenSocket, NULL, NULL); if (AcceptSocket == INVALID_SOCKET) { ........... } else ........... while(true) { lint lResult=0; lResult=recv(ListenSocket,(char *)&pack,sizeof(pack),0); ........... А теперь почитай чего возвращает accept в msdn
rudi, причем тут select? он пытается прочитать\писать данные из "слушающего" сокета, когда надо читать\писать в созданный сокет AcceptSocket который связывается с подключившимся клиентом
возник еще вопрос. как на сервере определить что клиент отключился? переписал код сервера в более удобный вид: Code: #ifndef UNICODE #define UNICODE #endif #include <winsock2.h> #include <stdio.h> #include <windows.h> #include "proto.h" // Need to link with Ws2_32.lib #pragma comment(lib, "Ws2_32.lib") void newclient(SOCKET AcceptSocket) { header pack; ZeroMemory((LPVOID)&pack,sizeof(pack)); while(WSAGetLastError()==0) { int lResult=0; lResult=recv(AcceptSocket,(char *)&pack,sizeof(pack),0); if(lResult==0) continue; else { if((pack.command==CS_HELLO)&&(pack.sing==SIGN)) { wprintf(L"Hello command recived!\n"); pack.command=SC_HELLO_ACK; send(AcceptSocket,(char *)&pack,sizeof(pack),0); wprintf(L"Hello_ack command sended..."); } } } wprintf(L"Client Disconnected...\n"); } int CreateServer() { //---------------------- // Initialize Winsock. WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != NO_ERROR) { wprintf(L"WSAStartup failed with error: %ld\n", iResult); return 1; } //---------------------- // Create a SOCKET for listening for // incoming connection requests. SOCKET ListenSocket; ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ListenSocket == INVALID_SOCKET) { wprintf(L"socket failed with error: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } //---------------------- // The sockaddr_in structure specifies the address family, // IP address, and port for the socket that is being bound. sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = htonl(INADDR_ANY); service.sin_port = htons(27015); if (bind(ListenSocket, (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) { wprintf(L"bind failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } //---------------------- // Listen for incoming connection requests. // on the created socket if (listen(ListenSocket, 1) == SOCKET_ERROR) { wprintf(L"listen failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } //---------------------- // Create a SOCKET for accepting incoming requests. SOCKET AcceptSocket; wprintf(L"Waiting for client to connect...\n"); //---------------------- // Accept the connection. while(true) { AcceptSocket = accept(ListenSocket, NULL, NULL); if (AcceptSocket == INVALID_SOCKET) { wprintf(L"accept failed with error: %ld\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } else { wprintf(L"Client connected.\n"); newclient(AcceptSocket); } } WSACleanup(); } int wmain(void) { return CreateServer(); }
realcoder, твой сервер сейчас только для оного клиента, остальные в очереди думаешь будут стоять ждать? посмотри тут хотя бы, не идеал но все же =)
спасибо. как по твоему несколько клиентов будут управлять одной машиной? если много клиентов, то я бы тогда функцию newclient сделал потоком: unsigned long __stdcall newclient(void *params) и создавал бы новый поток при получении соединения
ну так создавай через _beginthreadex() отдельный поток для каждого пользователя и обслуживай его там.