socket(api)问题(100分)

  • 主题发起人 主题发起人 阿伟~
  • 开始时间 开始时间

阿伟~

Unregistered / Unconfirmed
GUEST, unregistred user!
服务端测试代码:
var
gint_serSocket: Integer;
sock: TSocket;
WSAData: TWSAData;

function Tf_main.InitServerSocket: Boolean;
var
SockAddrIn: TSockAddrIn;
begin
Result := True;
if WSAStartUp($0101, WSAData) <> 0 then
begin
Memo1.Lines.Add('初始化WSA失败');
Result := False;
Exit;
end;
gint_serSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if gint_serSocket = INVALID_SOCKET then
begin
Memo1.Lines.Add('创建SOCKET失败');
Result := False;
Exit;
end;
SockAddrIn := InitSockAddrIn('', StrToInt(Trim(edt_port.Text)));
if bind(gint_serSocket, SockAddrIn, sizeof(SockAddrIn)) < 0 then
begin
closesocket(gint_serSocket);
Memo1.Lines.Add('SOCKET绑定失败');
Result := False;
end;
end;

function Tf_main.InitSockAddrIn(IP: string; Port: word): TSockAddrIn;
begin
Result.sin_family := PF_INET;
if IP <> '' then
Result.sin_addr.S_addr := inet_addr(pchar(IP))
else
Result.sin_addr.S_addr := INADDR_ANY;
Result.sin_port := htons(Port);
end;

procedure Tf_main.btn_listenClick(Sender: TObject);
begin
if InitServerSocket then
begin
if listen(gint_serSocket, 5) <> 0 then
begin
Memo1.Lines.Add('SOCKET监听失败');
Exit;
end;

end;
end;

procedure Tf_main.btn_sendClick(Sender: TObject);
var
s: string;
a: PChar;
begin
if Trim(edt_ml.Text) = '' then
begin
ShowMessage('请输入发送命令');
edt_ml.Clear;
edt_ml.SetFocus;
Exit;
end;
s := Trim(edt_ml.Text);
a := 'c';
{ if (send(gint_serSocket, a, 10, 0)) = SOCKET_ERROR then //Pointer(s)^
Memo1.Lines.Add('命令发送失败失败!');}
end;

procedure Tf_main.WMSocket(var Msg: TMessage);
var
str: string;
addr: TSockAddrIn;
addrlen: Integer;
a: array[0..23] of Char;
begin
case WSAGetSelectEvent(Msg.LParam) of
FD_ACCEPT:
begin
addrlen := sizeof(addr);
sock := accept(Msg.WParam, @addr, @addrlen);
if sock <> INVALID_SOCKET then
begin
WSAAsyncSelect(Msg.WParam, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE);
{ a := 'RCT36';
if (send(sock, a, 10, 0)) = SOCKET_ERROR then //Pointer(s)^
Memo1.Lines.Add('命令发送失败失败!');}
end;
end;
FD_CLOSE:
closesocket(Msg.WParam);
FD_READ:
begin
{recv(Msg.WParam, str[1], 1024, 0);
Memo1.Lines.Add(str);}
;
end;
FD_WRITE: ;
end;
end;

procedure Tf_main.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseSocket(gint_serSocket);
end;
××××××××××××××××××××××××××××××××××××××××
客户端代码:
unit u_main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, BaseGrid, AdvGrid, StdCtrls, ComCtrls, WinSock, IniFiles;

const WM_SOCKETEVENT = WM_USER + $1001; // Socket事件响应的消息

type
TSocketMessage = record // Socket消息的结构定义
Msg: Cardinal;
Socket: TSocket;
SelectEvent: Word;
SelectError: Word;
Result: Longint;
end;

type
Tf_main = class(TForm)
Panel1: TPanel;
M_COOL: TAnimate;
btn_begin: TButton;
memo1: TMemo;
sg_jl: TAdvStringGrid;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure btn_beginClick(Sender: TObject);
function InitClientSocket: Boolean;
procedure WMSocketEvent(var M: TSocketMessage); message WM_SOCKETEVENT;
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormClose(Sender: TObject; var Action: TCloseAction); //自定义SOCK消息
private
{ Private declarations }
public
{ Public declarations }
end;

var
f_main: Tf_main;

implementation

{$R *.dfm}
uses pub, u_set;
var
gint_Tran: Integer = 0;
gint_port: Integer;
gstr_address, gstr_send: string;
gint_CltSock: TSocket; //客户端套接字

procedure Tf_main.FormCreate(Sender: TObject);
var
s: string;
MyIni: TIniFile;
begin
if FileExists(ExtractFilePath(Paramstr(0)) + 'Internet.ini') then
begin
try
MyIni := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Internet.ini');
gstr_address := MyIni.ReadString('internet', 'IP', '');
gint_port := MyIni.ReadInteger('internet', 'port', 0);
finally
MyIni.Free;
end;
end;
s := '房号*10*日期*24*基价*10*其他费用*12*合计费用*14*';
title_sg_wy(sg_jl, s);
end;

procedure Tf_main.btn_beginClick(Sender: TObject);
var
SockAddrIn: TSockAddrIn;
begin
if not InitClientSocket then
begin
memo1.Lines.Text := '创建套接字失败';
Exit;
end;
SockAddrIn := InitSockAddrIn(gstr_address, gint_port);
WSAAsyncSelect(gint_CltSock, Handle, WM_SOCKETEVENT, FD_CONNECT);
memo1.Lines.Add('正在连接服务器' + gstr_address + '... ...');
WinSock.connect(gint_CltSock, SockAddrIn, SizeOf(TSockAddrIn));
end;

function Tf_main.InitClientSocket: Boolean;
begin
Result := True;
if InitWSA then
begin
gint_CltSock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if gint_CltSock = INVALID_SOCKET then
Result := False;
end
else
Result := False;
end;

procedure Tf_main.WMSocketEvent(var M: TSocketMessage);
var
Sock: TSocket;
str: string;
achr: Char;
begin
{
-----------------------------------------------------
WSAASyncSelect模型就是把一个窗口和套接字句柄建立起连接,
套接字的网络事件发生时时候,就会把某个消息发送到窗口,
然后可以在窗口的消息响应函数中处理数据的接收和发送。
----------------------------------------------------
}
Sock := M.Socket;
case M.SelectEvent of
FD_CONNECT:
if M.SelectError <> 0 then
begin
btn_begin.Enabled := True;
CloseSocket(M.Socket);
Memo1.Lines.Add('服务器忙,请稍后再试!');
end
else
begin
Memo1.Lines.Add('连接成功!');
btn_begin.Enabled := False;
achr := 'a';
if (send(Sock, achr, 2, 0)) = SOCKET_ERROR then
Memo1.Lines.Add('Error!');
WSAAsyncSelect(M.Socket, Handle, WM_SOCKETEVENT, FD_READ or FD_WRITE or FD_CLOSE);
end;
FD_READ:
begin
if Timer1.Enabled = True then
Timer1.Enabled := False;
recv(Sock, str[1], 20, 0);
if Pos('RCT36', str) > 0 then { TODO : 握手信号 }
begin
achr := Chr(6);
if (send(Sock, achr, 2, 0)) = SOCKET_ERROR then
Memo1.Lines.Add('握手信号回复失败!')
else
begin
Memo1.Lines.Add('握手信号回复!');
Timer1.Enabled := True;
end;
end;
end;
FD_WRITE:
;
FD_CLOSE:
begin
Memo1.Lines.Add('服务器已经断开连接');
shutdown(gint_CltSock, SD_BOTH);
CloseSocket(gint_CltSock);
end;
end;
end;

procedure Tf_main.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_F12:
begin
f_set := Tf_set.Create(Self);
f_set.ShowModal;
end;
end;
end;

procedure Tf_main.FormClose(Sender: TObject; var Action: TCloseAction);
begin
shutdown(gint_CltSock, SD_BOTH);
CloseSocket(gint_CltSock);
end;

end.
为什么我在客户段 achr := 'a';
if (send(Sock, achr, 2, 0)) = SOCKET_ERROR then
Memo1.Lines.Add('Error!');
WSAAsyncSelect(M.Socket, Handle, WM_SOCKETEVENT, FD_READ or FD_WRITE or FD_CLOSE);发送后,服务端始终没有收到消息呢?发送也是成功得。请各位达人帮我看看,谢谢
 
怎么在你的客户端程序里面,没有看到上面这一段呢?
 
有阿,你仔细看看
 
服务端应该在bind后调用WSAAsyncSelect,你忘记了为监听socket设置回调句柄。
 
还是不行,服务端就是始终无法进入到procedure Tf_main.WMSocket(var Msg: TMessage);消息过程里来,在客户端发送消息后,而且客户端发送消息显示已经成功发送
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1605817
 
SockAddrIn := InitSockAddrIn('', StrToInt(Trim(edt_port.Text)));

指定IP地址看看~~~~
 
拿分来吧~~~~~~~~~~~
 
指定了本机得IP127.0.0.1后还是无法进入到FD_READ里,在我客户端成功发送了数据之后
 
先mark,在look
 
WSAAsyncSelect(Msg.WParam, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE);
放到帧听前
不过要做些修改就可以了
 
在Listen的代码后面加
//服务端只挂接受连接事件
WSAAsyncSelect(gint_serSocket, Handle, WM_SOCKET, FD_Accept);

FD_Accept的处理代码段中作如下更改,
WSAAsyncSelect(Msg.WParam, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE);
改为:
WSAAsyncSelect(sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE);

自已调试一下,一切就都明白了。
 
leaber 是正确的。
你接受客户端连接过来的Socket挷定的参数错误。
 
我一直在关注这个帖子,也进行了多次尝试都不成功。按leaber的说法改了之后,客户端一连接就会收到服务器断开的消息。
 
//以下代码经过调试运行正常
//服务器端
unit server;

interface

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

const WM_SOCKETEVENT = WM_USER + $1001; // Socket事件响应的消息

type
TSocketMessage = record // Socket消息的结构定义
Msg: Cardinal;
Socket: TSocket;
SelectEvent: Word;
SelectError: Word;
Result: Longint;
end;

type
Tf_main = class(TForm)
Memo1: TMemo;
btn_listen: TButton;
btn_send: TButton;
edt_port: TEdit;
Edit1: TEdit;
Label1: TLabel;
function InitServerSocket: Boolean;
function InitSockAddrIn(IP: string; Port: Word): TSockAddrIn;
procedure btn_listenClick(Sender: TObject);
procedure btn_sendClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
procedure WMSocket(var Msg: TMessage); message WM_SOCKETEVENT;
{ Private declarations }
public
{ Public declarations }
end;

var
f_main: Tf_main;
gint_serSocket: Integer;
WSAData: TWSAData;
sock: TSocket;

implementation

{$R *.dfm}

function Tf_main.InitServerSocket: Boolean;
var
SockAddrIn: TSockAddrIn;
begin
Result := True;
if WSAStartUp($0101, WSAData) <> 0 then begin
Memo1.Lines.Add('初始化WSA失败');
Result := False;
Exit;
end;
gint_serSocket := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if gint_serSocket = INVALID_SOCKET then begin
Memo1.Lines.Add('创建SOCKET失败');
Result := False;
Exit;
end;
SockAddrIn := InitSockAddrIn('', StrToInt(Trim(edt_port.Text)));
if bind(gint_serSocket, SockAddrIn, sizeof(SockAddrIn)) < 0 then begin
closesocket(gint_serSocket);
Memo1.Lines.Add('SOCKET绑定失败');
Result := False;
end;

if listen(gint_serSocket, 5) <> 0 then begin
Memo1.Lines.Add('SOCKET监听失败');
Exit;
Result := False;
end;

if WSAAsyncSelect(gint_serSocket, Handle, WM_SOCKETEVENT, FD_ACCEPT or FD_CLOSE) <> 0 then begin
Memo1.Lines.Add('WSAAsyncSelect failur');
Exit;
Result := False;
end;
btn_listen.Enabled := False;
end;

function Tf_main.InitSockAddrIn(IP: string; Port: Word): TSockAddrIn;
begin
Result.sin_family := PF_INET;
if IP <> '' then
Result.sin_addr.S_addr := inet_addr(pchar(IP))
else
Result.sin_addr.S_addr := INADDR_ANY;
Result.sin_port := htons(Port);
end;

procedure Tf_main.btn_listenClick(Sender: TObject);
begin
InitServerSocket;
end;

procedure Tf_main.btn_sendClick(Sender: TObject);
var
a: string; //PChar;
begin
a := Edit1.Text;
if (send(sock, a[1], length(a), 0)) = SOCKET_ERROR then //Pointer(s)^
Memo1.Lines.Add('命令发送失败!');
end;

procedure Tf_main.WMSocket(var Msg: TMessage);
var
str: string;
addr: TSockAddrIn;
addrlen: Integer;
buf: array[0..4095] of Char;
len, i: Integer;
begin
if WSAGETSELECTERROR(Msg.lParam) <> 0 then begin
Memo1.Lines.Add('WSAGETSELECTERROR Wrong');
Exit;
end;
case WSAGetSelectEvent(Msg.lParam) of
FD_CONNECT: begin
Memo1.Lines.Add('connect');
//do nothing?
end;
FD_OOB: begin
Memo1.Lines.Add('FD_OOB');
end;
FD_ACCEPT: begin
addrlen := sizeof(addr);
sock := accept(Msg.WParam, @addr, @addrlen);
if sock <> INVALID_SOCKET then begin
Memo1.Lines.Add('sock成功');
WSAAsyncSelect(sock, Handle, WM_SOCKETEVENT, FD_READ or FD_WRITE or FD_CLOSE);
buf := 'RCT36';
if (send(sock, buf, length(buf), 0)) = SOCKET_ERROR then //Pointer(s)^
Memo1.Lines.Add('命令发送失败!')
else
Memo1.Lines.Add('命令发送成功!')
end;
end;
FD_CLOSE:
closesocket(Msg.WParam);
FD_READ: begin
len := recv(Msg.WParam, buf[0], 1024, 0);
str := '';
for i := 0 to len - 1 do
str := str + buf; //显示发送的内容
Memo1.Lines.Add(str);
;
end;
FD_WRITE: ;
end;
end;

procedure Tf_main.FormClose(Sender: TObject; var Action: TCloseAction);
begin
closesocket(gint_serSocket);
end;

end.
//客户端
unit client;
interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids {, BaseGrid, AdvGrid}, StdCtrls, ComCtrls, WinSock, IniFiles;

const WM_SOCKETEVENT = WM_USER + $1001; // Socket事件响应的消息

type
TSocketMessage = record // Socket消息的结构定义
Msg: Cardinal;
Socket: TSocket;
SelectEvent: Word;
SelectError: Word;
Result: Longint;
end;

type
Tf_main = class(TForm)
Panel1: TPanel;
btn_begin: TButton;
memo1: TMemo;
Timer1: TTimer;
Button1: TButton;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure btn_beginClick(Sender: TObject);
function InitClientSocket: Boolean;
function InitSockAddrIn(IP: string; Port: Word): TSockAddrIn;

procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject); //自定义SOCK消息
private
procedure WMSocketEvent(var M: TSocketMessage); message WM_SOCKETEVENT;
{ Private declarations }
public
{ Public declarations }
end;

var
Sock: TSocket;
f_main: Tf_main;

implementation

{$R *.dfm}
//uses pub, u_set;
var
gint_Tran: Integer = 0;
gint_port: Integer;
gstr_address, gstr_send: string;
gint_CltSock: TSocket; //客户端套接字

procedure Tf_main.FormCreate(Sender: TObject);
var
s: string;
MyIni: TIniFile;
begin
if FileExists(ExtractFilePath(Paramstr(0)) + 'Internet.ini') then begin
try
MyIni := TIniFile.Create(ExtractFilePath(Paramstr(0)) + 'Internet.ini');
gstr_address := MyIni.ReadString('internet', 'IP', '');
gint_port := MyIni.ReadInteger('internet', 'port', 0);
finally
MyIni.Free;
end;
end;
s := '房号*10*日期*24*基价*10*其他费用*12*合计费用*14*';
// title_sg_wy(sg_jl, s);
end;

function Tf_main.InitSockAddrIn(IP: string; Port: Word): TSockAddrIn;
begin
Result.sin_family := PF_INET;
if IP <> '' then
Result.sin_addr.S_addr := inet_addr(pchar(IP))
else
Result.sin_addr.S_addr := INADDR_ANY;
Result.sin_port := htons(Port);
end;

procedure Tf_main.btn_beginClick(Sender: TObject);
var
SockAddrIn: TSockAddrIn;
begin
if not InitClientSocket then begin
memo1.Lines.Text := '创建套接字失败';
Exit;
end;
SockAddrIn := InitSockAddrIn(gstr_address, gint_port);
WSAAsyncSelect(gint_CltSock, Handle, WM_SOCKETEVENT, FD_CONNECT or FD_READ or FD_WRITE or FD_CLOSE);
memo1.Lines.Add('正在连接服务器' + gstr_address + '... ...');
WinSock.connect(gint_CltSock, SockAddrIn, SizeOf(TSockAddrIn));
end;

function Tf_main.InitClientSocket: Boolean;
var
WSAData: TWSAData;
begin
Result := False;
if WSAStartUp($0101, WSAData) <> 0 then begin
memo1.Lines.Add('初始化WSA失败');
Result := False;
Exit;
end
else begin
gint_CltSock := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if gint_CltSock = INVALID_SOCKET then
Result := False
else
Result := True;
end;
end;

procedure Tf_main.WMSocketEvent(var M: TSocketMessage);
var
str: string;
buf: array[0..4095] of Char;
len, i: Integer;
begin
{
-----------------------------------------------------
WSAASyncSelect模型就是把一个窗口和套接字句柄建立起连接,
套接字的网络事件发生时时候,就会把某个消息发送到窗口,
然后可以在窗口的消息响应函数中处理数据的接收和发送。
----------------------------------------------------
}
Sock := M.Socket;
case M.SelectEvent of
FD_CONNECT:
if M.SelectError <> 0 then begin
btn_begin.Enabled := True;
CloseSocket(M.Socket);
memo1.Lines.Add('服务器忙,请稍后再试!');
end
else begin
memo1.Lines.Add('连接成功!');
btn_begin.Enabled := False;
WSAAsyncSelect(M.Socket, Handle, WM_SOCKETEVENT, FD_READ or FD_WRITE or FD_CLOSE);
buf := 'abcd';
if (send(M.Socket, buf, length(buf), 0)) = SOCKET_ERROR then
memo1.Lines.Add('Error!')
else
memo1.Lines.Add('success!');
end;
FD_READ: begin
if Timer1.Enabled = True then
Timer1.Enabled := False;
len := recv(Sock, buf[0], 4096, 0);
str := '';
for i := 0 to len - 1 do
str := str + buf; //显示发送的内容
memo1.Lines.Add(str);
if Pos('RCT36', str) > 0 then { TODO : 握手信号 } begin
buf := Chr(6);
if (send(Sock, buf, length(buf), 0)) = SOCKET_ERROR then
memo1.Lines.Add('握手信号回复失败!')
else begin
memo1.Lines.Add('握手信号回复!');
Timer1.Enabled := True;
end;
end;
end;
FD_WRITE:
;
FD_CLOSE: begin
memo1.Lines.Add('服务器已经断开连接');
shutdown(gint_CltSock, SD_BOTH);
CloseSocket(gint_CltSock);
end;
end;
end;

procedure Tf_main.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
{ case Key of
VK_F12:
begin
f_set := Tf_set.Create(Self);
f_set.ShowModal;
end;
end;}
end;

procedure Tf_main.FormClose(Sender: TObject; var Action: TCloseAction);
begin
shutdown(gint_CltSock, SD_BOTH);
CloseSocket(gint_CltSock);
end;

procedure Tf_main.Button1Click(Sender: TObject);
var
achr: string;
begin
achr := Edit1.Text;
send(Sock, achr[1], length(achr), 0);
end;

end.
 
.........................
 
呵呵,我以前的代码
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3100475
 
呵呵,我以前的代码
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3100475
 

Similar threads

S
回复
0
查看
911
SUNSTONE的Delphi笔记
S
S
回复
0
查看
888
SUNSTONE的Delphi笔记
S
后退
顶部