socket: возврат данных от сервера клиенту
Здравствуйте!
Пишу для себя пример работы с сокетами. Работа в асинхронном режиме, используя WinSock.
Клиент успешно подключается к серверу, данные успешно передаются от клиента к серверу, принимаются. При закрытии клиента также приходит сообщение о закрытии сокета, соединение завершается. Все хорошо, но... захотелось мне вернуть данные от сервера клиенту и все... Отправка данных клиенту вроде бы проходит без ошибок, а вот recv на клиенте ничего не возвращает.
В чем может быть проблема?
Ниже коды сервера и клиента.
Сервер:
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, WinSock, StdCtrls;
const
WM_SocketEvent = WM_USER + 1;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
ServSock: TSocket;
aBuf : array of char;
procedure WMSocketEvent(var msg: TMessage); message WM_SocketEvent;
procedure send_to_client(p_sock: TSocket);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Data: TWSAData;
Addr: TSockAddr;
begin
WSAStartup($101, Data);
ServSock := Socket(AF_Inet, Sock_Stream, IPPROTO_IP);
if ServSock = INVALID_SOCKET then ShowMessage('Îøèáêà');
Addr.sin_family := AF_Inet;
Addr.sin_addr.S_addr := inet_addr('127.0.0.1');
Addr.sin_port := HToNS(3320);
FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
Bind(ServSock, Addr, SizeOf(TSockAddr));
Listen(ServSock, SOMaxConn);
WSAAsyncSelect(ServSock, Handle, WM_SocketEvent, FD_Read or FD_Accept or FD_Connect or FD_Close);
end;
procedure TForm1.WMSocketEvent(var msg: TMessage);
var
Sock: TSocket;
SockError: integer;
SockName : TSockAddr;
vSize: integer;
vBuf: string;
BufSize : integer;
begin
Sock := TSocket(msg.WParam);
SockError := WSAGetSelectError(msg.LParam);
if SockError <> 0 then
begin
ShowMessage('Îøèáêà');
CloseSocket(Sock);
Exit;
end;
vSize := SizeOf(TSockAddr);
GetPeerName(Sock, SockName, vSize);
case WSAGetSelectEvent(msg.LParam) of
FD_Read:
begin
vSize := recv(Sock,aBuf[0],BufSize,0);
if vSize <= 0 then exit;
SetLength(vBuf,vSize);
lstrcpyn(@vBuf[1],@aBuf[0],vSize + 1);
Memo1.Lines.Add(format('Received from client: %s',[vBuf]));
send_to_client(Sock);
end;
FD_Accept:
begin
Sock := Accept(ServSock, nil, nil);
vSize := SizeOf(TSockAddr);
GetPeerName(Sock, SockName, vSize);
Memo1.Lines.Add(format('Client accepted, remote address [%s].',[inet_ntoa(SockName.sin_addr)]));
//Îïðåäåëÿåì ðàçìåð áóôåðà ÷òåíèÿ äëÿ ñîêåòà
vSize := sizeOf(BufSize);
getsockopt(Sock,SOL_SOCKET,SO_RCVBUF,PChar(@BufSize),vSize);
Memo1.Lines.Add(format('Receive buffer size [%d]',[BufSize]));
SetLength(aBuf,BufSize);
end;
FD_Close:
begin
Shutdown(Sock, SD_Send);
Memo1.Lines.Add(format('Client closed, remote address [%s].',[inet_ntoa(SockName.sin_addr)]));
CloseSocket(Sock);
end;
end;
end;
procedure TForm1.send_to_client(p_sock: TSocket);
var
buf: string;
begin
buf := 'asdasd';
if send(p_sock,buf[1],Length(buf),0) = SOCKET_ERROR then ShowMessage('Îøèáêà');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseSocket(ServSock);
WSACleanup;
end;
end.
Клиент:
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WinSock;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
ServSock: TSocket;
aBuf: array of char;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Data: TWSAData;
Addr: TSockAddr;
vSize, BufSize : integer;
begin
WSAStartup($101, Data);
ServSock := Socket(AF_Inet, Sock_Stream, IPPROTO_IP);
if ServSock = INVALID_SOCKET then ShowMessage('Îøèáêà');
Addr.sin_family := AF_Inet;
Addr.sin_addr.S_addr := inet_addr('127.0.0.1');
Addr.sin_port := HToNS(3320);
FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
if Connect(ServSock, Addr, SizeOf(TSockAddr)) = SOCKET_ERROR then ShowMessage('Îøèáêà');
vSize := sizeOf(BufSize);
if getsockopt(ServSock,SOL_SOCKET,SO_RCVBUF,PChar(@BufSize),vSize) = SOCKET_ERROR then ShowMessage('Îøèáêà');
Memo1.Lines.Add(format('Receive buffer size [%d]',[BufSize]));
SetLength(aBuf,BufSize);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
buf : string;
vSize: integer;
vBuf : string;
BufSize : integer;
begin
buf := Edit1.Text;
if send(ServSock,buf[1],Length(buf),0) = SOCKET_ERROR then ShowMessage('Îøèáêà');
repeat
vSize := recv(ServSock,aBuf[0],BufSize,0);
if vSize <> 0 then Break;
SetLength(vBuf,vSize);
lstrcpyn(@vBuf[1],@aBuf[0],vSize + 1);
Memo1.Lines.Add(format('Received from server: %s',[vBuf]));
until vBuf = 'q';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
closesocket(ServSock);
WSACleanup;
end;
end.
Заранее спасибо за ответ.
|