unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, WinSock, StdCtrls;
type
RECVPARAM = packed record
m_socket: TSocket;
m_handle: THANDLE;
end;
TForm1 = class(TForm)
btn_CloseSocket: TButton;
btn_SendData: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btn_CloseSocketClick(Sender: TObject);
procedure btn_SendDataClick(Sender: TObject);
private
{ Private declarations }
o_Msg: String;
m_socket: TSocket;
pRecvparam: RECVPARAM;
public
{ Public declarations }
function InitSocket(out Msg: String): Boolean;
end;
function RecvProc(lpParameter: Pointer):Integer; stdcall;
var
Form1: TForm1;
implementation
{$R *.dfm}
function RecvProc(lpParameter: Pointer):Integer; stdcall;
var
ilen: Integer;
m_socket: TSocket;
m_handle: THANDLE;
iRecvBytes: Integer;
addrSend: TSockAddrIn;
charBuf: array[0..1000] of char;
AcceptSocket: TSocket;
begin
Result := -1;
m_socket := RECVPARAM(Pointer(lpParameter)^).m_socket;
m_handle := RECVPARAM(Pointer(lpParameter)^).m_handle;
ilen := sizeof(TSockAddrIn);
FillChar(charBuf, sizeof(charBuf), 0);
while (TRUE) do
begin
AcceptSocket := accept(m_socket, @addrSend, @ilen);
if AcceptSocket = SOCKET_ERROR then
begin
MessageBox(m_handle, '接收连接异常', '测试', MB_ICONERROR);
Break;
end;
iRecvBytes := recv(AcceptSocket, charBuf, sizeof(charBuf), 0);
if (iRecvBytes = 0) or (iRecvBytes = SOCKET_ERROR) then
begin
MessageBox(m_handle, '接收数据异常', '测试', MB_ICONERROR);
Break;
end
else
MessageBox(m_handle, charBuf, '测试', MB_OK);
end;
MessageBox(m_handle, '跳出While循环', '测试', MB_OK) ;
Result := 0;
end;
function TForm1.InitSocket(out Msg: String): Boolean;
var
wsaData: TWSADATA;
iResult: Integer;
service: TSockAddrIn;
begin
Result := False;
iResult := WSAStartup(MAKEWORD(2,2), wsaData);
if (iResult <> NO_ERROR) then
begin
Msg := '初始化套接字库失败';
Exit;
end;
m_socket := socket(AF_INET,
SOCK_STREAM,
0);
if (m_socket = INVALID_SOCKET) then
begin
Msg := '创建套接字失败';
Exit;
end;
service.sin_family := AF_INET;
service.sin_port := htons(6010);
service.sin_addr.S_addr := inet_addr('127.0.0.1');
iResult := bind(m_socket, service, sizeof(TSockAddrIn));
if (iResult = SOCKET_ERROR) then
begin
Msg := '绑定套接字失败';
Exit;
end;
iResult := listen(m_socket, 0);
if (iResult = SOCKET_ERROR) then
begin
Msg := '监听套接字失败';
Exit;
end;
Result := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
hThread: THANDLE;
lpThreadId: DWORD;
begin
if not InitSocket(o_Msg) then
begin
MessageBox(Handle, PChar(o_Msg), '测试', MB_ICONERROR);
Exit;
end;
pRecvparam.m_socket := m_socket;
pRecvparam.m_handle := handle;
hThread := CreateThread(nil,
0,
@RecvProc,
@pRecvParam,
0,
lpThreadId);
CloseHandle(hThread);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
WSACleanup();
end;
procedure TForm1.btn_CloseSocketClick(Sender: TObject);
begin
closesocket(m_socket);
end;
procedure TForm1.btn_SendDataClick(Sender: TObject);
var
iSendBytes: Integer;
charBuf: array[0..1000] of char;
clientsevice: TSockAddrIn;
ConnectSocket: TSocket;
iLen, iResult: Integer;
begin
iLen := sizeof(TSockAddrIn);
clientsevice.sin_family := AF_INET;
clientsevice.sin_port := htons(6010);
clientsevice.sin_addr.S_addr := inet_addr('127.0.0.1');
ConnectSocket := socket(AF_INET,
SOCK_STREAM,
0);
iResult := connect(ConnectSocket,
clientsevice,
iLen);
if iResult = SOCKET_ERROR then
begin
MessageBox(Handle, '连接套接字异常', '测试', MB_ICONERROR);
Exit;
end;
FillChar(charBuf, sizeof(charBuf), 0);
StrPCopy(charBuf, '测试数据');
iSendBytes := send(ConnectSocket,
charBuf,
sizeof(charBuf),
0);
closesocket(ConnectSocket);
end;
end.
做个最检单的实验
TCP连接的阻塞模式的最简单原型
程序起动后会在下面这一行阻塞等待连接
AcceptSocket := accept(m_socket, @addrSend, @ilen);
当你执行下面这一句时程序从阻塞的地方往下正常执行,且能正常接收数据显示后,又会在上面那一句阻塞
iSendBytes := send(ConnectSocket,
charBuf,
sizeof(charBuf),
0);
OK,现在说明程序的流程没问题,现在来关闭监听的那个套接字,也就是m_socket
closesocket(m_socket);
你会发现下面这一行执行了
if AcceptSocket = SOCKET_ERROR then
begin
MessageBox(m_handle, '接收连接异常', '测试', MB_ICONERROR);
Break;
end;
这就说明你担心的那个问题并不存在