标签:图片 ons listen opened fail client startup art splay
server端
unit 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.
client端
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.
参考书籍:
windows网络编程 (第二版)
windows socket网络编程
补充说明:
server端不调用 shutdown 或 通过 setsockopt 设置 SO_LINGER 时, client 是收不到数据的。
这两个API实际上都起到了 ”延时“ 的效果。相当于在 closesocket 之前 sleep 了一下。
如何优雅的closesocket在《windows socket网络编程》一书中作者有说明。
标签:图片 ons listen opened fail client startup art splay
原文地址:https://www.cnblogs.com/Jiaojiawang/p/14310475.html