1

Trying to understood how to use ServerSocket and ClientSocket in Delphi. I made a simple chat programm but after client sends first message this error apperas (it happens during sending - just after server get's the message )

Windows socket error: Запрос на отправку или получение данных (when sending ona datagram socket using a sendto call)no adress was supplied (10057), on API 'getpeername'

Heres server code

unit Servert;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp;

type
  TForm1 = class(TForm)
    ServerSocket: TServerSocket;
    PortLabel: TLabel;
    Port: TEdit;
    Protocol: TGroupBox;
    mmoServer: TMemo;
    btnStart: TButton;
    btnStop: TButton;
    btnClear: TButton;
    btnEnd: TButton;
    btnSend: TButton;
    edtMsg: TEdit;
    lblUser: TLabel;
    procedure btnStartClick(Sender: TObject);
    procedure btnStopClick(Sender: TObject);
    procedure btnClearClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnEndClick(Sender: TObject);
    procedure ServerSocketClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocketClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocketClientError(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
      var ErrorCode: Integer);
    procedure ServerSocketClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure btnSendClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Usercount: Integer;

implementation

{$R *.dfm}

procedure TForm1.btnStartClick(Sender: TObject);
begin
  ServerSocket.Port:=StrToInt(Port.Text);
  ServerSocket.Active:=True;

  btnStart.Enabled:=False;
  btnStop.Enabled:=True;

  mmoServer.Lines.Add('Status: started');
end;

procedure TForm1.btnStopClick(Sender: TObject);
begin
ServerSocket.Port:=StrToInt(Port.Text);
  ServerSocket.Active:=False;

  btnStart.Enabled:=True;
  btnStop.Enabled:=False;

  mmoServer.Lines.Add('Status: stopped');
end;

procedure TForm1.btnClearClick(Sender: TObject);
begin
  mmoServer.Lines.Clear;
  mmoServer.Lines.Add('Server 1.0');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ServerSocket.Active:=False;
end;

procedure TForm1.btnEndClick(Sender: TObject);
begin
  ServerSocket.Active:=False;
  Application.Terminate;
end;



procedure TForm1.ServerSocketClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  mmoServer.Lines.Add('Status: Client ' + Socket.RemoteAddress + ' connected');
  Inc(Usercount);
  lblUser.Caption:= 'User:' + IntToStr(Usercount);
end;

procedure TForm1.ServerSocketClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  mmoServer.Lines.Add('Status: Client ' + Socket.RemoteAddress + ' disconnected');
  Dec(Usercount);
  lblUser.Caption:= 'User:' + IntToStr(Usercount);
end;

procedure TForm1.ServerSocketClientError(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
  mmoServer.Lines.Add('Status: Client ' + Socket.RemoteAddress + ' error:' + IntToStr(ErrorCode));
  Dec(Usercount);
  lblUser.Caption:= 'User:' + IntToStr(Usercount);
end;

procedure TForm1.ServerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var i:Integer; strRec:AnsiString;
begin
  strRec:=Socket.RemoteAddress + ': ' + Socket.ReceiveText;
  mmoServer.Lines.Add(strRec);

  for i:=0 to ServerSocket.Socket.ActiveConnections - 1 do  begin
    ServerSocket.Socket.Connections[i].SendText(strRec);
  end;


end;

procedure TForm1.btnSendClick(Sender: TObject);
var i:Integer;
begin
  for i:=0 to ServerSocket.Socket.ActiveConnections - 1 do
  begin
    ServerSocket.Socket.Connections[i].SendText('Ololo' + edtMsg.Text);
    mmoServer.Lines.Add('Ololo' + edtMsg.Text);
  end;
end;

end.

Here's client code

unit Client;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp, StdCtrls;

type
  TForm1 = class(TForm)
    lblHost: TLabel;
    edtHost: TEdit;
    lblPort: TLabel;
    edtPort: TEdit;
    btnConnect: TButton;
    btnDisconnect: TButton;
    grp1: TGroupBox;
    mmoClient: TMemo;
    grpSend: TGroupBox;
    mmoSend: TMemo;
    btnSend: TButton;
    ClientSocket: TClientSocket;
    procedure ClientSocketConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure btnDisconnectClick(Sender: TObject);
    procedure btnConnectClick(Sender: TObject);
    procedure ClientSocketDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure btnSendClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ClientSocketConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  mmoClient.Lines.Add('Status: connected ' + Socket.RemoteAddress);
end;

procedure TForm1.btnDisconnectClick(Sender: TObject);
begin
  ClientSocket.Host:=edtHost.Text;
  ClientSocket.Port:=StrToInt(edtPort.Text);
  ClientSocket.Active:=False;

  btnConnect.Enabled:=True;
  btnDisconnect.Enabled:=False;
end;

procedure TForm1.btnConnectClick(Sender: TObject);
begin
ClientSocket.Host:=edtHost.Text;
  ClientSocket.Port:=StrToInt(edtPort.Text);
  ClientSocket.Active:=True;

  btnConnect.Enabled:=False;
  btnDisconnect.Enabled:=True;
end;

procedure TForm1.ClientSocketDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
     mmoClient.Lines.Add('Status: disconnected ' + Socket.RemoteAddress)
end;

procedure TForm1.ClientSocketRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  mmoClient.Lines.Add(Socket.ReceiveText);
end;

procedure TForm1.btnSendClick(Sender: TObject);
begin
  ClientSocket.Socket.SendText(mmoSend.Text);
end;

end

.

DanilGholtsman
  • 2,354
  • 4
  • 38
  • 69
  • Please, provide more details: at which line of code (in the client or in the server) the error occurs (a stacktrace could help as well)? Is the first message sent ok, and only the second fails, or maybe it happens during sending the very first message? – Stan Nov 11 '12 at 13:54
  • @Stan oh yes it happens during very first message. I type it in client, I push send and it appears in server Memo thing but then suddenly theres an error appears – DanilGholtsman Nov 11 '12 at 14:00

2 Answers2

1

i'm really sorry if i'm posting this late, but i solved this issue and you might not see it.

in the server-side, make sure that you send to the socket by index, example:

ServerSocket1.Socket.Connections[SocketIndex].SendText();

Don't forget the .Connections property.

0

Error code 10057 is WSAENOTCONN, and getpeername() is the API function that the Socket.RemoteAddress property getter uses internally. This means you tried to read the RemoteAddress property of a Socket that was no longer connected to the server.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    As I said, the error means you are accessing the `RemoteAddress` property of a client that is no longer connected to the server. Since you only have a few places where you access the `RemoteAddress`, my guess would be that your loop inside the `OnClientRead` event is triggering an error that hits the `OnClientError` event, and then that client is gone before the `OnClientError` event handler can read its `RemoteAddress`. – Remy Lebeau Nov 12 '12 at 19:11