使用Winsock API发送/接收UDP包

其实Winsock这堆底层API和BSD都是一样的么…… 难怪令人怀疑这个是抄袭BSD的源代码……
UDP比较简单,只要bind一下,RP好的话就可以发了。
先 s: = socket(AF_INET,SOCK_DGRAM,0);
成功的话,s已经是一个可以用的socket了。

然后要指明绑定的addr
sa:sockaddr_in;
fillchar(sa,sizeof(sa),0);
sa.sin_family:=AF_INET;
sa.sin_port:=htons(port);
sa.sin_addr.S_addr:=inet_addr(PChar(address));
address为地址(a.b.c.d形式),port为端口号。而htons作用是把以主机存储方式存储的port转换为网络上通用的port形式。

接着就可以bind了
bind(s,sa,sizeof(sa));
成功的话,netstat -an能够看见你所bind的端口号。

bind完了,这个socket和端口也就建立了联系,所有扔到这个口的UDP包都会给这个socket

接着可以直接用recv收。但是假如没有数据过来,程序就会卡在这里,多不好……
所以用WSAAsyncSelect来指明当收到包之后给窗口发消息。
WSAAsyncSelect(s,form1.Handle,WM_RECEIVED,FD_READ);
WM_RECEIVED自己定义,FD_READ说明只关心收到消息。

接着让窗口收到这种消息的时候运行给定的proc
先定义这个proc:
Procedure TForm1.OnMyMessage(var Msg:TMsg;var Handled:Boolean);
然后在FormCreate的时候告诉窗口:
application.OnMessage:=OnMyMessage;
这样就完了

收到消息后:
  if Msg.message=WM_RECEIVED then
(万一不是呢……)
lParam的底字节代表具体情况(我们只关心FD_READ,所以这里只会是FD_READ)
高字节为出错信息
wParam为收到消息的那个socket,我们这里只有s,所以其实也一样
然后就可以recv了
recv(Msg.wParam,data,MAXMSG,0);
不出意外,消息就在data里了~

好好处理消息吧~

记得最后closesocket(s)哦~ 以免资源浪费~

 

Old Blog Link: http://computer.mblogger.cn/henryhu/posts/61586.aspx

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.