最近一直在搞winsock api实现udp协议消息的接收,结果老有问题....
以下是部分代码:(根据api-guide的实例改编)
SelectOps = FD_READ Or FD_WRITE Or FD_CONNECT Or FD_CLOSE
If WSAAsyncSelect(sID, FWND,WINSOCKMSG, ByVal SelectOps) <> 0 Then
waste = closesocket(sID)
Exit Function
End If
MyHWND = SetWindowLong(FWND, GWL_WNDPROC, AddressOf MyFunc)
问题来啦:
1.调试的时候,我运行另外的程序隔2秒就往某个端口广播信息,可是我的消息处理函数根本就接收不到WINSOCKMSG消息...
2.WSAAsyncSelect函数申明的时候,各参数都有ByVal,可是调用的时候为什么还带上了?
大家帮帮忙啊~~~
以下是部分代码:(根据api-guide的实例改编)
SelectOps = FD_READ Or FD_WRITE Or FD_CONNECT Or FD_CLOSE
If WSAAsyncSelect(sID, FWND,WINSOCKMSG, ByVal SelectOps) <> 0 Then
waste = closesocket(sID)
Exit Function
End If
MyHWND = SetWindowLong(FWND, GWL_WNDPROC, AddressOf MyFunc)
问题来啦:
1.调试的时候,我运行另外的程序隔2秒就往某个端口广播信息,可是我的消息处理函数根本就接收不到WINSOCKMSG消息...
2.WSAAsyncSelect函数申明的时候,各参数都有ByVal,可是调用的时候为什么还带上了?
大家帮帮忙啊~~~
解决方案 »
- 有数据传输,却不触发WebBrowser1_DocumentComplete事件的多框架网页,怎么对其进行操作
- 新手请教~怎样显示内存中的dib图像呢?请大家进来看看!
- 稍微复杂点,小弟刚学几天,多多指教
- VB开发模块外包!!
- 如何限制textbox控件只能输入0-9数字,其它不能输入?
- 组件安装报错
- 紧急求援!!!!!!!!!!!!!
- 如何判断ACCESS数据库中存在某一字段?
- 软件发布!欢迎大家帮助测试。
- 有谁知道可以从网上下载 vb5 的,最好是http网址?
- vb 变量是不是 在定义完了马上就可以 初始化 ,不必放到 过程里 去初始化,像下面这样可以吧?
- 急 啊 。。请查看程序错误否!!
3.bind函数可以绑定端口、IP地址,setsockopt也可以设置。两个函数有什么差别啊?分别用在什么情况下的什么地方呢?
Private Function WinSockUDPGetMAC(sIP As String)
Dim sockfd As Long
Dim t_NB As NetbiosNS
'UDP发送包
t_NB.buff(0) = &H0
t_NB.buff(1) = &H0
t_NB.buff(2) = &H0
t_NB.buff(3) = &H0
t_NB.buff(4) = &H0
t_NB.buff(5) = &H1
t_NB.buff(6) = &H0
t_NB.buff(7) = &H0
t_NB.buff(8) = &H0
t_NB.buff(9) = &H0
t_NB.buff(10) = &H0
t_NB.buff(11) = &H0
t_NB.buff(12) = &H20
t_NB.buff(13) = &H43
t_NB.buff(14) = &H4B
Dim i As Integer
For i = 15 To 44
t_NB.buff(i) = &H41
Next
t_NB.buff(45) = &H0
t_NB.buff(46) = &H0
t_NB.buff(47) = &H21
t_NB.buff(48) = &H0
t_NB.buff(49) = &H1
Dim aa As String
aa = Hex(inet_addr("10.17.45.24"))
If Len(aa) < 8 Then aa = 0 & aa
Dim SocketBuffer As FSockAddrIn
SocketBuffer.Sin_family = AF_INET
SocketBuffer.Sin_port = htons(137)
SocketBuffer.Sin_addr = CLng("&H" & aa)
SocketBuffer.Sin_zero = String$(8, 0)sockfd = socket(AF_INET, SOCK_DGRAM, 0) 'UDP通信
Dim Irc As Integer
Irc = sendto(sockfd, t_NB, 50, 0, SocketBuffer, Len(SocketBuffer))
If Irc = -1 Then MsgBox "错误"
End Function
Private Const SOCKET_MESSAGE As Long = WM_USER + &H401
Private Const lngEvents As Long = FD_READ Or FD_WRITE Or FD_ACCEPT Or FD_CONNECT Or FD_CLOSE
...
'用钩子钩住窗口的信息,当窗口收到信息时用模块中的 SockInfoProc 来处理窗口所取得的所有信息
SockWindowProc = GetWindowLong(SockWindowhWnd, GWL_WNDPROC)
SetWindowLong SockWindowhWnd, GWL_WNDPROC, AddressOf SockInfoProc
'让窗口有接受网络事件信息的能力
ReturnLong = WSAAsyncSelect(SockRequestID, SockWindowhWnd, SOCKET_MESSAGE, lngEvents)
'判断异步信息设置是否成功
If ReturnLong <> 0 Then
mvarState = sckError
CancelERR = False
RaiseEvent SockError(11003, "不可恢复的错误。", 0, "WinSock.Listen", "", 0, CancelERR)
If CancelERR = False Then
Err.Raise vbObjectError + 11003, "不可恢复的错误。", 11003, "", 0
End If
Exit Sub
End If
...
我这段代码是想修改网上关于利用UDP137发包获得主机信息的的DELPHI和C代码,把他改成VB版式的,但总还是不行,发包这段就错误了!
现在我贴上那段DELPHI代码,供大家参考,希望对大家在winsock编程中有所帮助,也希望有能力的朋友,把这体段代码改成VB版的!
{局域网IP搜索}
unit U_FrmSearchNetIp;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
WinSock,Forms, Dialogs, RXSpin, StdCtrls, ExtCtrls, Buttons, RXSplit,
Grids, ComCtrls, RxRichEd;const
WM_SOCK = WM_USER + 1; {自定义windows消息}
NBTPORT = 137; {向对方的137端口发数据包(UDP包)}Type
TTGroupNet=record {网络标识}
IP:string;
ComputerName:string;
ComputerDes:string;
NetGroup:string;
NetMacCode:string;
end;
type
TFrmSearchNetIp = class(TForm)
Panel2: TPanel;
Panel1: TPanel;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
EdNetIP1: TEdit;
EdNetIP2: TEdit;
Panel3: TPanel;
Panel4: TPanel;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
SgDispNetIP: TStringGrid;
TabSheet2: TTabSheet;
Panel5: TPanel;
Panel6: TPanel;
SBrnScanNetIP: TSpeedButton;
SBtnStopScan: TSpeedButton;
LabIP: TLabel;
LabStartTime: TLabel;
LabEndTime: TLabel;
LabTime: TLabel;
Label4: TLabel;
TabSheet3: TTabSheet;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SBtnStopScanClick(Sender: TObject);
procedure SBrnScanNetIPClick(Sender: TObject);
procedure SgDispNetIPSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
procedure SgDispNetIPDblClick(Sender: TObject);
private
{ Private declarations }
procedure ReadData(var Message: TMessage); message WM_SOCK; {消息接送}
Procedure ClearGrid();
Procedure MakeGrid(Const IntIndex:integer=3);{排序} public
{ Public declarations }
end;{*******************************************************}
TComread=class(TThread) {通讯线程}
private
public
Tagg:integer;
protected
procedure Execute; override;
end;
{始化SOCKET}
Procedure WinSockInital(Handle: HWnd);
{关闭SOCKET}
Procedure WinSockClose();
const NbtstatPacket:array[0..49]of byte {发送数据包}
=($0,$0,$0,$0,$0,$1,
$0,$0,$0,$0,$0,$0,$20,$43,$4b,
$41,$41,$41,$41,$41,$41,$41,$41,
$41,$41,$41,$41,$41,$41,$41,$41,
$41,$41,$41,$41,$41,$41,$41,$41,
$41,$41,$41,$41,$41,$41,$0,$0,$21,$0,$1);
{*******************************************************}
var
FrmSearchNetIp: TFrmSearchNetIp; TF_stop:boolean; {停止}
TempWSAData: TWSAData;
sockfd:TSocket; {Integer socket句柄}
WAIT_ACK_EVENT:Thandle; {LongWord 句柄|}
FSockAddrIn : TSockAddrIn; IP_count,ComputerIP:integer;
IP_end: Dword;
StartTickCount:DWORD ; {计数器}
StopTickCount: DWORD ; TGroupNet:array of TTGroupNet;{网络信息寄存}
IntGridCol:integer;
implementation{$R *.DFM}procedure TFrmSearchNetIp.FormCreate(Sender: TObject);
begin
IntGridCol:=0;
{TRxRichEdit 去除64K的限制}
RxRedDispinf.MaxLength := High(Integer) - 1024;
{Grid清除 ClearGrid}
ClearGrid;
end;
procedure TFrmSearchNetIp.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
TF_stop:=True;
setlength(TGroupNet,0);
{关闭SOCKET}
WinSockClose();
end;
{停止扫描}
procedure TFrmSearchNetIp.SBtnStopScanClick(Sender: TObject);
begin
TF_stop:=True;
end;
{始化SOCKET}
Procedure WinSockInital(Handle: HWnd);
begin
{ 1 初始化SOCKET}
TF_stop:=false;
if WSAStartup(2, TempWSAData)=1 then
begin
showmessage('Socket初始化出错');
exit
end;
{若是用UDP通信,则用}
sockfd:=Socket(AF_INET,SOCK_DGRAM,0); FSockAddrIn.SIn_Family := AF_INET;
FSockAddrIn.SIn_Port := htons(NBTPORT); {137端口} {Socket的信息传递--》From.Handle 窗体, FD_READ 在读就绪的时候, WM_SOCK 自定义消息号}
WSAAsyncSelect(sockfd, Handle , WM_SOCK, FD_READ);
{创建事件}
WAIT_ACK_EVENT:=CreateEvent(nil,true,false,pchar('WAIT_ACK') );
ResetEvent(WAIT_ACK_EVENT);
end;
{关闭SOCKET}
Procedure WinSockClose();
begin
TF_stop:=True;
CloseSocket(sockfd); {closesocket函数用来关闭一个描述符为sockfd套接字}
WSACleanup;
sleep(2);
end;
{****************** SOCKET通讯 *****************}
{扫描开始}
procedure TFrmSearchNetIp.SBrnScanNetIPClick(Sender: TObject);
var
DWx1,Dwx:Dword;
IP,Str_Ip:string;
Tcomr:TComread;
begin
RxRichEdit1.text:='';
Setlength(TGroupNet,0);
{始化SOCKET}
WinSockInital(FrmSearchNetIp.Handle); {清除Grid}
ClearGrid;
TF_stop:=false;
IP:=trim(EdNetIP1.text);
RxRedDispinf.Text :='';
label4.Caption:='IP个数:';
LabIP.caption:='';
LabStartTime.caption:='开始时间:';
LabEndTime.caption:='结束时间:';
LabTime.caption:='扫描用时:';
if Longword(inet_addr(pchar(IP)))=INADDR_NONE then
begin
Messagebox(Application.handle,pchar(IP + ' TP 出错'),'警告',MB_OK+MB_ICONERROR);
exit;
end;
IP:=trim(EdNetIP2.text);
if Longword(inet_addr(pchar(IP)))=INADDR_NONE then
begin
Messagebox(Application.handle,pchar(IP + ' TP 出错'),'警告',MB_OK+MB_ICONERROR);
exit;
end;
IP:=trim(EdNetIP1.text);
ComputerIP:=inet_addr(PChar(IP)) ; // 192.168.0.1 ===>01 00 A8 C0
str_ip:=inttohex(ComputerIP,8); //01 00 A8 C0
str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2); //==> C0 A8 00 01
DWx:=strtoint('$'+str_ip); {转换成为一个长整形数} str_ip:=inttohex(ComputerIP,8);
str_ip:=inttostr(strtoint('$' + copy(str_ip,7,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,5,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,3,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,1,2)));
EdNetIP1.text:=str_ip; {允许输入 一个数值表示IP} IP:=trim(EdNetIP2.text);
ComputerIP:=inet_addr(PChar(IP)) ; // 192.168.0.1 ===>01 00 A8 C0
str_ip:=inttohex(ComputerIP,8); //01 00 A8 C0
str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2); //==> C0 A8 00 01
DWx1:=strtoint('$'+str_ip); {转换成为一个长整形数} str_ip:=inttohex(ComputerIP,8);
str_ip:=inttostr(strtoint('$' + copy(str_ip,7,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,5,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,3,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,1,2)));
EdNetIP2.text:=str_ip; {允许输入 一个数值表示IP} if DWx1>Dwx then
begin
IP_count:=DWx1-Dwx;
ComputerIP:=inet_addr(PChar(trim(EdNetIP1.text)));
IP_end:=DWx1;
label1.caption:='-->>';
end
else begin
IP_count:=DWx-Dwx1;
ComputerIP:=inet_addr(PChar(trim(EdNetIP2.text)));
IP_end:=DWx;
label1.caption:='<<--';
end; SBrnScanNetIP.Enabled :=false; {屏蔽按键}
Tcomr:=TComread.Create(True);
StartTickCount:=GetTickCount;
LabStartTime.caption:='开始时间:' + FloatToStr(StartTickCount);
Tcomr.Resume ; {开始线程}
end;
{ TComread }
{通讯线程}
procedure TComread.Execute;
var
str_ip:string;
IP_now:Dword;
Procedure MakeEnd();
begin
FrmSearchNetIp.SBrnScanNetIP.Enabled :=True;
StopTickCount:=GetTickCount;
FrmSearchNetIp.LabEndTime.caption:='结束时间:' +FloatToStr(StopTickCount);
FrmSearchNetIp.LabTime.caption:='扫描用时:' +FloatToStr(StopTickCount-startTickCount)+' mS';
FrmSearchNetIp.label4.Caption:='IP个数:'+ inttostr(FrmSearchNetIp.SgDispNetIP.RowCount-1);
FrmSearchNetIp.MakeGrid(3);
{排序
'TP地址'0 '计算机名称'1 '计算机描述' 2
'网络组'3 '网卡MAC码'4
MakeGrid(const IntIndex: integer=3);}
end;
begin with FrmSearchNetIp do
begin
str_ip:=inttohex(ComputerIP,8); //01 00 A8 C0
str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2); //==> C0 A8 00 01
IP_now:=strtoint('$'+str_ip); while IP_end>=IP_now do ////IP_end==> C0 A8 00 01
begin
if TF_stop=True then
begin
MakeEnd();
{关闭SOCKET}
WinSockClose();
exit;
end;
str_ip:=inttohex(ComputerIP,8);
str_ip:=inttostr(strtoint('$' + copy(str_ip,7,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,5,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,3,2)))
+'.' + inttostr(strtoint('$' + copy(str_ip,1,2)));
LabIP.caption:=str_ip; {目前扫描的IP} FSockAddrIn.SIn_Addr.S_addr := ComputerIP;//inet_addr(pchar(IP));
str_ip:=inttohex(ComputerIP,8); //01 00 A8 C0
str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2); //==> C0 A8 00 01
str_ip:=inttohex( strtoint(('$' + str_ip))+1,8); //==> 加一C0 A8 00 02
IP_now:=strtoint('$'+str_ip);
str_ip:=copy(str_ip,7,2)+copy(str_ip,5,2)+copy(str_ip,3,2)+copy(str_ip,1,2); //==>02 00 A8 C0
ComputerIP:=strtoint('$'+str_ip);
sendto(sockfd, NbtstatPacket,50, 0, FSockAddrIn, sizeof(FSockAddrIn));
//发送数据后
waitforsingleobject(WAIT_ACK_EVENT,trunc( RxSEdDelay.Value)); // 等待事件变成有信号
ResetEvent(WAIT_ACK_EVENT); // 设为没有信号
end;
MakeEnd();
end;
{关闭SOCKET}
WinSockClose();
end;
{ TFrmSearchNetIp }
{消息接送}
procedure TFrmSearchNetIp.ReadData(var Message: TMessage);
var
Buffer: Array [1..500] of byte;
flen,len,i,j,pos,name_num: integer;
Event: word;
IP:string;
str_tp,str:string;
str_list_IP,str_list_name,str_list_disp,str_list_group,str_list_MAC:string;
StrTp:string;
begin
flen:=sizeof(FSockAddrIn);
Event := WSAGetSelectEvent(Message.LParam);
if Event = FD_READ then
begin
len := recvfrom(sockfd, buffer, sizeof(buffer), 0, FSockAddrIn, flen);
if len> 0 then
begin
//FSockAddrIn.sin_addr.S_un_b.s_b1
with FSockAddrIn.sin_addr.S_un_b do
IP:=format('%d.%d.%d.%d',[ord(s_b1),ord(s_b2),ord(s_b3),ord(s_b4)]);
str_list_IP:=IP;
//数据分析
name_num:=0;
str_tp:='';
for i:=1 to len do
begin
if((buffer[i]=$21)and(buffer[i+1]=$00)and(buffer[i+2]=$01)) then
begin
name_num:=buffer[i+9];
break;
end;
end;
if name_num=0 then exit;
pos:=i+10;
str:='';
for i:=pos to (pos+18*name_num-1) do
begin
if (((i-pos)mod 18) =0) then
begin
for j:=0 to 14 do
begin
if trim(char(buffer[i+j]))='' then buffer[i+j]:=ord(' ');
str:=str+char(buffer[i+j]);
end;
if (buffer[i+16] and $80)=$80 then
begin
if buffer[i+15]=$0 then str_list_GROUP:=trim(str); //网络组
str:=str+format('<%x>',[buffer[i+15]]);
str:=str+'<GROUP>';
end
else begin
if buffer[i+15]=$20 then str_list_name:=trim(str) //计算机名
else
if buffer[i+15]=$3 then str_list_disp:=trim(str);//计算机说明
str:=str+format('<%x>',[buffer[i+15]]);
str:=str+'<UNIQUE>';
end;
str_tp:=str_tp + str +#13+#10;
str:='';
end;
end;
for i:=0 to 5 do
begin
str:=str+format('%.2x.',[buffer[i+pos+18*name_num]]);
end;
delete(str,length(str),1);
str_list_MAC:=trim(str); //网卡的MAC码
str:='MAC: '+str;
str_tp:=str_tp + str + #13+#10;
{网络信息}
RxRedDispinf.Text :=RxRedDispinf.Text +IP + #13+#10+ str_tp+ #13+#10;
{Grid}
I:=SgDispNetIP.RowCount;
if I=2 then
begin
if trim(SgDispNetIP.Cells[0,1])<>'' then
begin
Inc(i);
SgDispNetIP.RowCount:=I;
end;
end
else begin
Inc(i);
SgDispNetIP.RowCount:=I;
end;
Dec(i);
SgDispNetIP.Cells[0,i]:=str_list_IP;//'TP地址'
SgDispNetIP.Cells[1,i]:=str_list_name;//'计算机名称'
SgDispNetIP.Cells[2,i]:=str_list_disp;//'计算机描述'
SgDispNetIP.Cells[3,i]:=str_list_GROUP;//'网络组'
SgDispNetIP.Cells[4,i]:=str_list_MAC;//'网卡MAC码'
{
RichEdit1.Text :=RichEdit1.Text + str_list_IP + ' ' + str_list_name + ' ' +
str_list_disp + ' ' + str_list_GROUP +' ' + str_list_MAC+ #13+#10
}
setlength(TGroupNet,high(TGroupNet)+2);
TGroupNet[high(TGroupNet)].IP:=str_list_IP;//'TP地址'
TGroupNet[high(TGroupNet)].ComputerName :=str_list_name;//'计算机名称'
TGroupNet[high(TGroupNet)].ComputerDes:=str_list_disp;//'计算机描述'
TGroupNet[high(TGroupNet)].NetGroup:=str_list_GROUP;//'网络组'
TGroupNet[high(TGroupNet)].NetMacCode :=str_list_MAC;//'网卡MAC码' StrTp:=str_list_IP + ' ' +str_list_name+ ' ' +
str_list_disp + ' ' + str_list_GROUP + ' ' +
str_list_MAC;
RxRichEdit1.Lines.Add(StrTp);
end;
SetEvent(WAIT_ACK_EVENT);//有信号
end;
end;
{Grid清除 ClearGrid}
procedure TFrmSearchNetIp.ClearGrid;
begin
SgDispNetIP.RowCount:=2;
SgDispNetIP.Rows[1].Text:='';
SgDispNetIP.Cells[0,0]:='TP地址' ;
SgDispNetIP.Cells[1,0]:='计算机名称' ;
SgDispNetIP.Cells[2,0]:='计算机描述' ;
SgDispNetIP.Cells[3,0]:='网络组' ;
SgDispNetIP.Cells[4,0]:='网卡MAC码' ;
end;
问题可能在bind函数,函数返回值虽然是0,但是我用超级兔子的进程管理器检查一下,已经使用的端口列表里面根本就没有我绑定的端口...
这是怎么回事呢???
还有,使用winsock控件的时候会被windows防火墙拦截,但是调用api就没有,是因为本来就不会被拦截,还是因为我的api调用不成功呢?可是我的函数返回值都表示很成功啊...
Copy后到这里出错,不理解