Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Поток для клиента описан следующим образом

procedure TServerThread.ClientExecute;
begin
  while not Terminated do
  begin
    txt:=ClientSocket.ReceiveText;
    if txt='TEXT' then
    begin
      Synchronize(Update);
      ClientSocket.SendText('Привет');
    end;
  end;
end;
procedure TServerThread.Update;
begin
  Form1.cmd.Lines.Add(txt);
end;


По нажатию батона клиент всякий раз отсылает 'TEXT'. И сервер каждый раз его получает нормально.
Но почему клиент не получает 'Привет'? Обработчик OnRead не срабатывает.
3 ноя 18, 18:49    [21723353]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 46152

OxY63rus
Но почему клиент не получает 'Привет'? Обработчик OnRead не срабатывает.

Поскольку кода клиента ты не показал, вангую, что он из сокета не читает.

Posted via ActualForum NNTP Server 1.5

3 ноя 18, 20:06    [21723390]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, братан, привожу код
procedure TForm1.CliRead(Sender: TObject; Socket: TCustomWinSocket);
begin
  cmd.Lines.Add(Socket.ReceiveText);
end;

Как же я мог забыть его привести.
3 ноя 18, 20:18    [21723394]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, отправка
procedure TForm1.Button5Click(Sender: TObject);
begin
  if Cli.Active then Cli.Socket.SendText('TEXT');
end;
3 ноя 18, 20:20    [21723396]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, вабанк кидаю текст юнита. Клиент и сервер в одной программе

+

unit Unit1;

interface

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

type
    TServerThread = class(TServerClientThread)
    txt: string;
    procedure ClientExecute; override;
    procedure Update;
end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Cli: TClientSocket;
    Serv: TServerSocket;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    cmd: TMemo;
    Button5: TButton;
    Button6: TButton;
    SelFile: TOpenDialog;
    Button7: TButton;
    Button8: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure ServClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure Button3Click(Sender: TObject);
    procedure ServClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServGetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      var SocketThread: TServerClientThread);
    procedure ServClientError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure ServClientRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure CliDisconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure CliError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure CliRead(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  F,FN: TFileStream;

implementation

{$R *.dfm}

procedure TServerThread.ClientExecute;
begin
  while not Terminated do
  begin

    txt:=ClientSocket.ReceiveText;

    if txt='TEXT' then
    begin
      Synchronize(Update);
      ClientSocket.SendText('Ïðèâåò');
      //ClientSocket.Close;
      //Terminate;
    end;
  end;
end;

procedure TServerThread.Update;
begin
  Form1.cmd.Lines.Add(txt);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Serv.Port:=6600;
  Serv.ServerType:=stThreadBlocking;
  Serv.Active:=true;
  cmd.Lines.Add('Server started');
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  Serv.Active:=false;
  cmd.Lines.Add('Îñòàíîâëåí');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Cli.Host:='localhost';
  Cli.Port:=6600;
  Cli.ClientType:=ctBlocking;
  Cli.Active:=true;
  cmd.Lines.Add('Cli Connecting...');
end;

procedure TForm1.ServClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  cmd.Lines.Add('Connect');
  //FN:= TFileStream.Create('c:\temp\new.txt',fmCreate);
  //FN.Position:=0;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Cli.Active:=false; ;//(Cli.Socket.Handle);
  cmd.Lines.Add('Disconnecting...');
end;

procedure TForm1.ServClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  //FN.Free;

  cmd.Lines.Add('Disconnect');
end;

procedure TForm1.ServGetThread(Sender: TObject;
  ClientSocket: TServerClientWinSocket;
  var SocketThread: TServerClientThread);
begin
  cmd.Lines.Add('GetThread');
      SocketThread:=TServerThread.Create(true, ClientSocket);
      SocketThread.Priority:=tpNormal;
      SocketThread.FreeOnTerminate:=true;
      SocketThread.Resume;
end;

procedure TForm1.ServClientError(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  cmd.Lines.Add('Error '+ inttostr(ErrorCode));
  ErrorCode:=0;
end;

procedure TForm1.ServClientRead(Sender: TObject; Socket: TCustomWinSocket);
var Buf: array [0..8192] of Char;
    IncLen,BufLen: integer;
begin
  cmd.Lines.Add('!!!!!!!!!!ÏÐÈÍßÒÎ!!!!!!!!!!!');
  IncLen:=Socket.ReceiveLength;
  while IncLen>0 do
  begin
    BufLen:=Socket.ReceiveBuf(Buf,SizeOf(Buf));
    if BufLen<=0 then break else FN.WriteBuffer(Buf,BufLen);
  end;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  if Cli.Active then Cli.Socket.SendText('TEXT');
end;

procedure TForm1.Button6Click(Sender: TObject);
var len: integer;
begin
  SelFile.Execute;
  if FileExists(SelFile.filename) then
  begin
    F:=TFileStream.Create(SelFile.filename,fmOpenRead);
    try
        Cli.Socket.SendStream(F);
    except;
        F.Free;
    end;
  end;
end;

procedure TForm1.Button7Click(Sender: TObject);
var a,b,c: Char;
begin
  a:='a';
  b:='b';
  c:='c';
  showmessage(inttostr(ord(c) XOR ord(a)));

end;

procedure TForm1.Button8Click(Sender: TObject);
var i: integer;
label Skip;
begin
  for i:=1 to 65535 do
  begin
    try
      Serv.Port:=i;
      Serv.ServerType:=stNonblocking;
      Serv.Active:=true;
      Serv.Active:=false;
    except
      Serv.Active:=false;
      cmd.Lines.Add('&#207;&#238;&#240;&#242; '+inttostr(i)+' &#231;&#224;&#237;&#255;&#242;');
    end;
  end;
end;

procedure TForm1.CliDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  cmd.Lines.Add('Disconnect');
end;

procedure TForm1.CliError(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  cmd.Lines.Add('Error');
  ErrorCode:=0
end;

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

end.

3 ноя 18, 20:24    [21723398]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 46152

Ты клиенту поток создать забыл.

Posted via ActualForum NNTP Server 1.5

3 ноя 18, 20:37    [21723407]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, как так?
procedure TForm1.ServGetThread(Sender: TObject;
  ClientSocket: TServerClientWinSocket;
  var SocketThread: TServerClientThread);
begin
  cmd.Lines.Add('GetThread');
      SocketThread:=TServerThread.Create(true, ClientSocket);
      SocketThread.Priority:=tpNormal;
      SocketThread.FreeOnTerminate:=true;
      SocketThread.Resume;
end;

Есть же
3 ноя 18, 20:44    [21723409]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 46152

OxY63rus
Есть же

TClientSocket
Set ClientType to ctNonBlocking to enable the client socket to respond to asynchronous
reading and writing events. When ClientType is ctNonBlocking, execution is not blocked by
reading and writing over the socket connection. OnRead or OnWrite events occur when the
socket needs to read or write over the connection.

When ClientType is ctBlocking, use a TWinSocketStream object for reading and
writing.

Posted via ActualForum NNTP Server 1.5

3 ноя 18, 21:10    [21723424]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, офигеть. Спасибо за науку. А , собсно, где это делать? OnConnect клиента? А из чего? приму любые заумные ссылки по теме. За исключением отсылок к Socket API от живодёров
3 ноя 18, 21:20    [21723432]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, начитал . Буду пробовать. Если что подыму тему
3 ноя 18, 21:51    [21723440]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Я правильно понимаю, что у TWinSocketStream я не смогу получить ReceiveLength и мне придётся с отправляющей стороны оканчивать отправляемую строку нулевым чаром, а на принимающей стороне разгребать весь буфер до нулевого чара? :(
3 ноя 18, 23:23    [21723458]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3621
OxY63rus
а на принимающей стороне разгребать весь буфер
Это делать в любом случае придется. Никакой магии в ReceiveText не будет.
Будет 1-й раз "TEX", 2-й раз - "T".
4 ноя 18, 01:11    [21723478]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 2922
OxY63rus,

Indy позволяет получить строку целиком:

https://stackoverflow.com/questions/19371049/delphi-indy-readln-with-timeout
4 ноя 18, 01:42    [21723479]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
makhaon, про Indy не желаю ничего слышать по религиозным соображениям ;) прости
4 ноя 18, 11:23    [21723546]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 46152

OxY63rus
про Indy не желаю ничего слышать по религиозным соображениям

Но при этом используешь компоненты, которые по кривизне недалеко от него ушли. Ню-ню...

Posted via ActualForum NNTP Server 1.5

4 ноя 18, 12:42    [21723570]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Dimitry Sibiryakov, я не говорю о безупречности scktcomp, а о том, что я не буду добавлять Id из-за одной функции
4 ноя 18, 13:03    [21723576]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 2922
OxY63rus,

Тогда страдай :)
4 ноя 18, 14:28    [21723608]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10605
OxY63rus
мне придётся с отправляющей стороны оканчивать отправляемую строку нулевым чаром, а на принимающей стороне разгребать весь буфер до нулевого чара? :(
Есть две модели пересылки данных по сокету

1. Каждое сообщение заканчивать неким терминатором
2. В начале каждого сообщения отправляется заголовочный пакет фиксированной длины, в котором указывается длина сообщения

Других вариантов для адекватной работы системы нет
5 ноя 18, 19:36    [21724508]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
OxY63rus
Member

Откуда:
Сообщений: 130
Не буду создавать тему, подниму эту.
Подскажите, если в потоке я буду работать с сокетами (в рантайме создавать ClientSocket) в неблокирующем режиме, это просто не прилично так делать или черевато какими-то ситуациями?
16 ноя 18, 13:12    [21736292]     Ответить | Цитировать Сообщить модератору
 Re: Работа с сокетами в блокирующем режиме  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 46152

Это не имеет смысла. Вся суть TClientSocket - лежать на форме в design-time. В любом
другом случае гораздо проще и удобнее пользоваться функциями winsock непосредственно.

Posted via ActualForum NNTP Server 1.5

16 ноя 18, 14:06    [21736369]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить