📄 gbnunit.pas
字号:
unit GBNUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ExtCtrls;
type
TClientForm1 = class(TForm)
Button2: TButton;
Edit1: TEdit;
Timer1: TTimer;
ATimer: TTimer;
ResendTimer: TTimer;
Memo2: TMemo;
Memo1: TMemo;
AtoBerr: TCheckBox;
BtoAerr: TCheckBox;
Button1: TButton;
A: TClientSocket;
B: TClientSocket;
Server: TServerSocket;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
Button3: TButton;
Panel1: TPanel;
GroupBox3: TGroupBox;
Label1: TLabel;
Label3: TLabel;
Image1: TImage;
Panel2: TPanel;
GroupBox4: TGroupBox;
procedure FormCreate(Sender: TObject);
procedure BRead(Sender: TObject; Socket: TCustomWinSocket);
procedure ARead(Sender: TObject; Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure ServerClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerClientRead(Sender: TObject; Socket: TCustomWinSocket);
procedure Timer1Timer(Sender: TObject);
procedure Send(i: Integer);
procedure StartTimer();
procedure StopTimer();
procedure ATimerTimer(Sender: TObject);
function GetLastStr(Str: String; num: Integer): String;
function GetFirStr(Str: String; num: Integer): String;
procedure ResendTimerTimer(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
N=5;
var
ClientForm1: TClientForm1;
APort, BPort: Integer; //记录是哪一个ClientSocket的RemotePort
rcvMsg: String; //记录Server收到的Message
Data: String; //记录发送端A要发送的数据
NextSeqNum, Base, ExpectedSeqNum, SentNum, ResendBase: Integer;
returnMsg: String; //接收端B要发回的ACD内容
toAMsg: String; //发送端A最后收到的数据
LastSent: Integer; //发送端A最后发出的数据包序号
implementation
{$R *.dfm}
{$R 1.RES}
procedure TClientForm1.FormCreate(Sender: TObject);
begin
Server.Active := true;
A.Active := true;
B.Active := true;
Memo1.Text := '';
Memo2.Text := '';
Base := 0;
NextSeqNum := 0;
ExpectedSeqNum := 0;
SentNum := 0;
end;
procedure TClientForm1.Send(i: Integer);
begin
Edit1.SetFocus;
Edit1.SelStart := SentNum * 10 + i;
Edit1.SelLength := 1;
LastSent := i;
A.Socket.SendText(IntToStr(i)+': ' + Edit1.SelText);
end;
procedure TClientForm1.BRead(Sender: TObject; Socket: TCustomWinSocket);
begin
toAMsg := Socket.ReceiveText;
if (GetFirStr(toAMsg, 3) = 'ACK') then
begin
if (StrToInt(GetLastStr(toAMsg, 1)) = 9) then SentNum := SentNum + 1;
Base := StrToInt(GetLastStr(toAMsg, 1)) + 1;
ATimer.Enabled := false;
//SentNum := SentNum + 1;
if (Base = NextSeqNum) then
StopTimer
else
StartTimer;
end;
end;
procedure TClientForm1.ARead(Sender: TObject; Socket: TCustomWinSocket);
var
tmp: String;
begin
tmp := Socket.ReceiveText;
if (ExpectedSeqNum = StrToInt(GetFirStr(tmp, 1))) and (Length(tmp) > 1) then
begin
Memo2.Lines.Add(tmp);
returnMsg := 'ACK _________' + IntToStr(ExpectedSeqNum);
B.Socket.SendText(returnMsg);
ExpectedSeqNum := ExpectedSeqNum + 1;
if ExpectedSeqNum > 9 then ExpectedSeqNum := 0;
end
else
begin
B.Socket.SendText(returnMsg);
end;
end;
procedure TClientForm1.Button2Click(Sender: TObject);
begin
//B.Socket.SendText(Edit1.Text);
Data := Edit1.Text;
//Edit1.Text := '';
Timer1.Enabled := true;
Button2.Enabled := false;
end;
procedure TClientForm1.ServerClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
tmp: integer;
begin
BPort := Socket.RemotePort;
APort := Socket.RemotePort;
if (APort < BPort) then
begin
tmp := APort;
APort := BPort;
BPort := tmp;
end;
end;
procedure TClientForm1.ServerClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
rcvMsg := Socket.ReceiveText;
if (Socket.RemotePort = APort) then
if BtoAerr.Checked then
begin
//如果A到B出错,则“网络”什么都不干
end
else
begin
Memo1.Lines.Add('B-->A: ' + rcvMsg);
Server.Socket.Connections[1].SendText(rcvMsg);
end
else
if AtoBerr.Checked then
begin
//如果B到A出错,则“网络”什么都不干
end
else
begin
Memo1.Lines.Add('A-->B: ' + rcvMsg);
Server.Socket.Connections[0].SendText(rcvMsg);
end
end;
procedure TClientForm1.Timer1Timer(Sender: TObject);
begin
if (NextSeqNum < Base + N) then
begin
Send(NextSeqNum);
if (Base = NextSeqNum) then StartTimer;
NextSeqNum := NextSeqNum + 1;
if NextSeqNum > 9 then NextSeqNum := 0;
end
else
begin
end;
if (Edit1.SelStart >= Length(Edit1.Text)-1) and (StrToInt(GetLastStr(toAMsg, 1)) = LastSent - 1) then Timer1.Enabled := false;
end;
procedure TClientForm1.StartTimer();
begin
ATimer.Enabled := true;
end;
procedure TClientForm1.StopTimer();
begin
ATimer.Enabled := false;
end;
function TClientForm1.GetLastStr(Str: String; num: Integer): String;
var
tmpArr: Array[0..1000] of char;
tmpStr: String;
i: Integer;
begin
StrPCopy(tmpArr, Str);
tmpStr := '';
for i := Length(Str) - num to Length(Str) do
tmpStr := tmpStr + tmpArr[i];
Result := tmpStr;
end;
function TClientForm1.GetFirStr(Str: String; num: Integer): String;
var
tmpArr: Array[0..1000] of char;
tmpStr: String;
i: Integer;
begin
StrPCopy(tmpArr, Str);
for i := 0 to num - 1 do
tmpStr := tmpStr + tmpArr[i];
Result := tmpStr;
end;
procedure TClientForm1.ATimerTimer(Sender: TObject);
begin
StartTimer;
ResendBase := Base;
NextSeqNum := Base;
ResendTimer.Enabled := true;
end;
procedure TClientForm1.ResendTimerTimer(Sender: TObject);
begin
if (ResendBase <= NextSeqNum - 1) then
begin
Send(ResendBase);
ResendBase := ResendBase + 1;
end
else
begin
ResendTimer.Enabled := false;
end;
end;
procedure TClientForm1.Button1Click(Sender: TObject);
begin
Edit1.Text := '';
AtoBerr.Checked := false;
BtoAerr.Checked := false;
Button2.Enabled := true;
Timer1.Enabled := false;
ResendTimer.Enabled := false;
A.Active := false;
B.Active := false;
Server.Active := false;
Server.Active := true;
A.Active := true;
B.Active := true;
Memo1.Text := '';
Memo2.Text := '';
Base := 0;
NextSeqNum := 0;
ExpectedSeqNum := 0;
SentNum := 0;
Edit1.SetFocus;
end;
procedure TClientForm1.Button3Click(Sender: TObject);
begin
ClientForm1.Close ;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -