Delphi API Socket通讯接收不到数据。

Mr Dang 2014-01-15 03:03:14
与TCP调试助手做服务器,下面程序能正常发送数据,就是接收不到数据,哪里有问题?

客户端程序

unit Unit1;

interface

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

type
TSocketComm=class(TObject)
private
function ConnectSvr: Integer;
function SendFrame(Str_SendFrame: string): Integer;

public
constructor Create;
destructor Destroy; override;

end;

type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
edt_SendFrame: TEdit;
mmo_Debug: TMemo;
btn3: TButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure btn3Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;


var
Form1: TForm1;
skt:TSocket;
LExit:Boolean;
Svr_Addr,Clnt_Addr:TSockAddr;
ClientSocket:TSocketComm;

procedure Receive(Sock :TSocket);stdcall;

implementation

{$R *.dfm}

constructor TSocketComm.Create;
var
Wsa:TWSAData;
begin
inherited Create;
if WSAStartup(MakeWord(2,2),Wsa)<>0 then
begin
ShowMessage('Init Socket failed');
WSACleanup;
end;
end;

destructor TSocketComm.Destroy;
begin
inherited destroy;
WSACleanup;
closesocket(skt);
end;

function TSocketComm.ConnectSvr():Integer;
var
dThreadID:DWORD;
i_RtnCode:Integer;
begin
skt:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if skt=INVALID_SOCKET then
begin
ShowMessage('Create Socket failed');
WSACleanup;
Exit;
end;
Clnt_Addr.sin_family:=AF_INET;
Clnt_Addr.sin_addr.S_addr:=inet_addr('127.0.0.1');
Clnt_Addr.sin_port:=htons(StrToInt('2039'));
bind(skt,Clnt_Addr,SizeOf(Clnt_Addr));

Svr_Addr.sin_family:=AF_INET;
Svr_Addr.sin_addr.S_addr:=inet_addr('192.168.200.95');
Svr_Addr.sin_port:=htons(StrToInt('2038'));
i_RtnCode:=connect(skt,Svr_Addr,SizeOf(Svr_Addr));

if i_RtnCode<>0 then
begin
ShowMessage('Connect 192.168.200.95 failed');
WSACleanup;
Exit;
end;
LExit:=False;
BeginThread(nil, 0, @Receive, PChar(skt),0, dThreadID);
end;

procedure Receive(Sock :TSocket);stdcall;
var
BufRecv: pChar;
iRes: Integer;
begin
GetMem(BufRecv, 1024);
while not LExit do
begin
iRes := recv(Sock, BufRecv^, 1024, 0);
if iRes < 1 then
begin
Sleep(500);
Continue;
end;

Form1.mmo_Debug.Lines.Add(BufRecv);
ZeroMemory(bufRecv, 1024);
end;
FreeMem(BufRecv);
CloseSocket(Sock);
ExitThread(0);
end;

function TSocketComm.SendFrame(Str_SendFrame:string):Integer;
var
i,i_FrameLen:Integer;
i_Buf:array[1..1024] of Byte;
begin
Str_SendFrame:=StringReplace(Str_SendFrame,' ','',[rfReplaceAll]);
i_FrameLen:=Length(Str_SendFrame) div 2; //Convert string to byte string
for i:=0 to i_FrameLen-1 do
begin
i_Buf[i+1]:=StrToInt('$'+Copy(Str_SendFrame,i*2+1,2));
end;
send(skt,i_Buf,i_FrameLen,0);
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
ClientSocket:=TSocketComm.Create;
ClientSocket.ConnectSvr;
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
// closesocket(skt);
WSACleanup;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
ClientSocket.SendFrame(Trim(edt_SendFrame.Text));
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
btn2Click(nil);
end;

end.

...全文
223 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Mr Dang 2014-01-15
  • 打赏
  • 举报
回复
Delphi API Socket 发送,接收十六进制数据 代码调通的贴下面了。

unit Unit1;

interface

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

type
  TSocketComm=class(TObject)
  private

  public
    constructor Create;
    destructor Destroy; override;
    function ConnectSvr: Integer;
    function SendFrame(Str_SendFrame: string): Integer;
  end;

type
  TForm1 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    edt_SendFrame: TEdit;
    mmo_Debug: TMemo;
    btn3: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;
  skt:TSocket;
  LExit:Boolean;
  Svr_Addr,Clnt_Addr:TSockAddr;
  ClientSocket:TSocketComm;

procedure Receive(Sock:TSocket);

implementation

{$R *.dfm}

constructor TSocketComm.Create;
var
    Wsa:TWSAData;
begin
    inherited Create;
    if WSAStartup(MakeWord(2,2),Wsa)<>0 then
    begin
        ShowMessage('Init Socket failed');
        WSACleanup;
    end;
end;

destructor TSocketComm.Destroy;
begin
    inherited destroy;
    WSACleanup;
    closesocket(skt);
end;

function TSocketComm.ConnectSvr():Integer;
var
    dThreadID:DWORD;
    i_RtnCode:Integer;
begin
    skt:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if skt=INVALID_SOCKET then
    begin
        ShowMessage('Create Socket failed');
        WSACleanup;
        Exit;
    end;
    Clnt_Addr.sin_family:=AF_INET;
    Clnt_Addr.sin_addr.S_addr:=inet_addr('127.0.0.1');
    Clnt_Addr.sin_port:=htons(StrToInt('2039'));
    bind(skt,Clnt_Addr,SizeOf(Clnt_Addr));

    Svr_Addr.sin_family:=AF_INET;
    Svr_Addr.sin_addr.S_addr:=inet_addr('192.168.200.95');
    Svr_Addr.sin_port:=htons(StrToInt('2038'));
    i_RtnCode:=connect(skt,Svr_Addr,SizeOf(Svr_Addr));

    if i_RtnCode<>0 then
    begin
        ShowMessage('Connect 192.168.200.95 failed');
        WSACleanup;
        Exit;
    end;
    LExit:=False;
    BeginThread(nil, 0, @Receive, PChar(skt),0, dThreadID);
end;

procedure Receive(Sock:TSocket);
var
  Buffer: pChar;
  i,iRes: Integer;
  S,Str_RecByte:string;
  i_Buf:array[1..1024] of Byte;
begin
    GetMem(Buffer, 1024);
    while not LExit do
    begin
        iRes := recv(Sock, Buffer^, 1024, 0);
        if iRes < 1 then
        begin
            Sleep(500);
            Continue;
        end;
        Move(Buffer^,i_Buf,iRes);
        for i:=1 to iRes do
        begin
            Str_RecByte:=IntToHex(i_Buf[i],2);
            S:=S+' '+Str_RecByte;
        end;
        if Copy(S,1,1)=' ' then
        begin
            Delete(S,1,1);
        end;
        Form1.mmo_Debug.Lines.Add(S);
        ZeroMemory(Buffer, 1024);
    end;
    FreeMem(Buffer);
   // CloseSocket(skt);
    ExitThread(0);
end;

function TSocketComm.SendFrame(Str_SendFrame:string):Integer;
var
    i,i_FrameLen:Integer;
    i_Buf:array[1..1024] of Byte;
begin
    Str_SendFrame:=StringReplace(Str_SendFrame,' ','',[rfReplaceAll]);
    i_FrameLen:=Length(Str_SendFrame) div 2;              //Convert string to byte string
    for i:=0 to i_FrameLen-1 do
    begin
        i_Buf[i+1]:=StrToInt('$'+Copy(Str_SendFrame,i*2+1,2));
    end;
    send(skt,i_Buf,i_FrameLen,0);
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
    ClientSocket:=TSocketComm.Create;
    ClientSocket.ConnectSvr;
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
//    closesocket(skt);
    WSACleanup;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
    ClientSocket.SendFrame(Trim(edt_SendFrame.Text));
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    btn2Click(nil);
end;

end.

Mr Dang 2014-01-15
  • 打赏
  • 举报
回复
to pathletboy :学习了,我单步调的时候我也看到了Sock的值变了,我就没传参了,我后来临时一想,改成我上面的那样,也可以收到数据,就是没注意到stdcall,pathletboy正解。
pathletboy 2014-01-15
  • 打赏
  • 举报
回复
引用 8 楼 a295281315 的回复:
to truexf: to pathletboy: 感谢你们2位,问题解决了,线程函数多加了个stdcall导致接收不到数据。
delphi默认是pascal传参方式,前3个参数用寄存器,然后再用堆栈传参,stdcall是直接用堆栈传参,你线程函数定义为堆栈传参的话是无法接收到正确的参数的。
Mr Dang 2014-01-15
  • 打赏
  • 举报
回复
to truexf: to pathletboy: 感谢你们2位,问题解决了,线程函数多加了个stdcall导致接收不到数据。
pathletboy 2014-01-15
  • 打赏
  • 举报
回复
引用 5 楼 a295281315 的回复:
to truexf: 啥都没收到。 我把 BeginThread(nil, 0, @Receive, PChar(skt),0, dThreadID); 改成 BeginThread(nil, 0, @Receive, nil,0, dThreadID); procedure Receive(Sock :TSocket);stdcall;改成 procedure Receive();stdcall; 可以接受到数据了,Why?
你线程函数的定义不对
function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
  ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
  var ThreadId: LongWord): Integer;
type
  TThreadFunc = function(Parameter: Pointer): Integer;
这么定义
function Receive(Sock :TSocket): Integer;
Mr Dang 2014-01-15
  • 打赏
  • 举报
回复
to pathletboy:嗯,好的,我记住了,我这个是练手程序,以前没用过API写SOCKET.这里调通了,再写到其他地方去的。
Mr Dang 2014-01-15
  • 打赏
  • 举报
回复
to truexf: 啥都没收到。 我把 BeginThread(nil, 0, @Receive, PChar(skt),0, dThreadID); 改成 BeginThread(nil, 0, @Receive, nil,0, dThreadID); procedure Receive(Sock :TSocket);stdcall;改成 procedure Receive();stdcall; 可以接受到数据了,Why?
pathletboy 2014-01-15
  • 打赏
  • 举报
回复
先确定服务器端是否有返回数据,另外,不要在非主线程中操作vcl,例如118行就是错误的用法。
「已注销」 2014-01-15
  • 打赏
  • 举报
回复
引用 2 楼 a295281315 的回复:
to truexf :用TCP&UDP测试工具 做的服务器。我在测试工具中发的数据.这边程序就是收不到数据。
那你收什么?既然服务器没有数据发过来你的recv函数就会阻塞在哪里
Mr Dang 2014-01-15
  • 打赏
  • 举报
回复
to truexf :用TCP&UDP测试工具 做的服务器。我在测试工具中发的数据.这边程序就是收不到数据。
「已注销」 2014-01-15
  • 打赏
  • 举报
回复
你确定服务器有返回数据吗?

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧