winsocket tcp练习一
2021-03-01 15:26
标签:图片 ons listen opened fail client startup art splay server端 client端 参考书籍: windows网络编程 (第二版) windows socket网络编程 补充说明: server端不调用 shutdown 或 通过 setsockopt 设置 SO_LINGER 时, client 是收不到数据的。 这两个API实际上都起到了 ”延时“ 的效果。相当于在 closesocket 之前 sleep 了一下。 如何优雅的closesocket在《windows socket网络编程》一书中作者有说明。 winsocket tcp练习一 标签:图片 ons listen opened fail client startup art splay 原文地址:https://www.cnblogs.com/Jiaojiawang/p/14310475.htmlunit ServerMainFormUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Win.ScktComp, Winapi.WinSock;
type
TForm2 = class(TForm)
ServerSocket1: TServerSocket;
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
var
wsData: TWSAData;
ServerSocket, ClientSocket: TSocket;
ServerAddr, ClientAddr: TSockAddr;
len: Integer;
buf: TBytes;
ErrorCode: Integer;
L: TLinger;
begin
WSAStartup($0101, wsData);
ServerAddr.sin_port := htons(6000);
ServerAddr.sin_family := PF_INET;
ServerAddr.sin_addr.S_addr := INADDR_ANY;
ServerSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(ServerSocket, ServerAddr, SizeOf(ServerAddr));
listen(ServerSocket, 10);
len := SizeOf(ClientAddr);
ClientSocket := accept(ServerSocket, @ClientAddr, @len);
buf := BytesOf(‘jjw‘);
if send(ClientSocket, Buf[0], Length(buf), 0) = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode = WSAEWOULDBLOCK then
memo1.Lines.Add(‘WSAEWOULDBLOCK‘)
else
memo1.Lines.Add(ErrorCode.ToString);
end;
// shutdown(ClientSocket, 1); 这行代码和下面的代码都能解决 client接收不到数据的问题。
L.l_onoff := 1;
L.l_linger := 1;
setsockopt(
ClientSocket,
SOL_SOCKET, SO_LINGER,
PAnsiChar(@L),
SizeOf(L)
);
if closesocket(ClientSocket) = SOCKET_ERROR then
memo1.Lines.Add(‘close error‘);
closesocket(ServerSocket);
WSACleanup;
end;
end.
unit ClientMainFormUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Win.ScktComp, Winapi.Winsock,
Vcl.StdCtrls;
type
TForm2 = class(TForm)
ClientSocket1: TClientSocket;
Memo1: TMemo;
Button1: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
procedure ClientSocket1Write(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
var
WSAData: TWsaData;
ASocket: TSocket;
addr: TSockAddrIn;
FDSet: TFDSet;
buf: array[0..1023] of AnsiChar;
dataBuf: AnsiString;
TimeVal: TTimeVal;
ret: Integer;
begin
if WSAStartup($0101, WSAData) 0 then
raise Exception.Create(‘WSAStartup Error‘);
addr.sin_family := AF_INET;
addr.sin_port := htons(6000);
addr.sin_addr.S_addr := inet_addr(‘192.168.1.37‘);
ASocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if ASocket = INVALID_SOCKET then
raise Exception.Create(‘ASocket Error‘);
if connect(ASocket, addr, SizeOf(addr)) = SOCKET_ERROR then
raise Exception.Create(‘connect Failed.‘);
dataBuf := ‘jjwgood‘;
send(ASocket, PAnsiChar(dataBuf)^, length(databuf), 0);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 100;
while not CheckBox1.Checked do
begin
FD_ZERO(FDSet);
FD_SET(ASocket, FDSet);
ret := select(0, @FDSet, nil, nil, @TimeVal);
if ret = SOCKET_ERROR then
begin
memo1.Lines.Add(‘select read error: ‘ + WSAGetLastError.ToString);
Break;
end;
if ret > 0 then
begin
if FD_ISSET(ASocket, FDSet) then
begin
ret := recv(ASocket, buf, 1024, 0);
if ret = SOCKET_ERROR then
begin
Memo1.Lines.Add(‘read error‘);
Break;
end
else if ret = 0 then
begin
Memo1.Lines.Add(‘server closed‘);
Break;
end
else
Memo1.Lines.Add(buf);
end;
end;
FD_ZERO(FDSet);
FD_SET(ASocket, FDSet);
ret := select(0, nil, @FDSet, nil, @TimeVal);
if ret = SOCKET_ERROR then
begin
memo1.Lines.Add(‘select write error: ‘ + WSAGetLastError.ToString);
Break;
end;
if ret > 0 then
begin
if FD_ISSET(ASocket, FDSet) then
begin
if CheckBox2.Checked then
begin
dataBuf := ‘test‘;
send(ASocket, PAnsiChar(dataBuf)^, length(databuf), 0);
CheckBox2.Checked := False;
end;
end;
end;
Application.ProcessMessages;
end;
closesocket(ASocket);
WSACleanup;
end;
procedure TForm2.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
begin
memo1.Lines.Add(‘read‘);
end;
procedure TForm2.ClientSocket1Write(Sender: TObject; Socket: TCustomWinSocket);
begin
memo1.Lines.Add(‘write‘);
end;
end.