Udp数据接收端实现

来源:互联网 发布:linux snmp下载 编辑:程序博客网 时间:2024/05/05 00:38
Udp数据接收端实现
----Delphi实现
Lanno Ckeeke        LC2005052202
概要
此程序本想与上一篇实现的功能相同,代码是在delphi6编写。与C++程序相比,其发送端发送数据太快,在一个for循环中连续调用sendto20次,则此程序将不能完全接收到数据。若在for循环中每发送一次数据后 sleep(200),则此程序可以接收全部的数据。这就是UDP数据传输的不可靠性吗?而C++程序(LC2005052201)则不会出现此现象。进一步考虑中。。。。。。
说明
所用到的函数与LC2005052201相同,可以参见上一篇文章。
窗体中一个Button用于启动程序进行必要的socket设置,并开始接收数据(处于阻塞状态);一个EditBox用于显示接收数据的次数;一个ListBox用于显示已接收到的数据。
 
变量说明在代码中有详细的注释。
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.  Dialogs, StdCtrls,Winsock;
  8.  
  9. type
  10.  TForm1 = class(TForm)
  11.     Button2: TButton;    //开始接收数据
  12.     ListBox1: TListBox; //将接收到的数据显示到列表中
  13.     Edit1: TEdit;        //显示接收了多少次数据
  14.     procedure Button2Click(Sender: TObject);
  15.  private
  16.     { Private declarations }
  17.  public
  18.     { Public declarations }
  19.  end;
  20.  
  21.  procedure CheckRc(szErr : PChar);
  22.  
  23. var
  24.  Form1: TForm1;
  25. const
  26.        DEFAULT_PORT = 5150;    //接收端口号
  27.  DEFAULT_COUNT = 20;     //接收20次
  28.  DEFAULT_BUFFER_LENGTH = 4096//接收数据的最大缓冲区大小
  29. var
  30.        nPort : Integer = DEFAULT_PORT;
  31.  dwCount : DWORD = DEFAULT_COUNT;
  32.  dwLength : DWORD = DEFAULT_BUFFER_LENGTH ;
  33.  szInterface : array[0..31of char;
  34.  
  35.  wsd : WSAData; //保存初始化信息
  36.  soRecv : TSOCKET; //接收数据的socket
  37.  pszRecv: PChar;   //接收数据的缓冲区指针
  38.  nRet : integer;
  39.  i : integer;
  40.  dwSenderSize : Integer;
  41.  siSender,local : SOCKADDR_IN;
  42.  nError : Integer;
  43.  
  44. implementation
  45.  
  46. {$R *.dfm}
  47. procedure CheckRc(szErr : PChar);
  48. begin
  49.  MessageBox(0,szErr,'Error',MB_OK);
  50. end;
  51.  
  52. procedure TForm1.Button2Click(Sender: TObject);
  53. var
  54.        i: integer;
  55.  nLastError : Integer;
  56.  nNumOfRecv : Integer;
  57. begin
  58.        nNumOfRecv := 0;
  59.  //初始化socket
  60.        nError := WSAStartup(MakeWord(2,2),wsd);
  61.  if Boolean(nError) then
  62.      MessageBox(0,'WSAStartup','Error',MB_OK);
  63.  //建立socket
  64.  soRecv := socket(AF_INET,SOCK_DGRAM,0);
  65.  if soRecv = SOCKET_ERROR then
  66.  begin
  67.      CheckRc('socket');
  68.  end;
  69.  
  70.   //设置端口与地址
  71.  local.sin_family := AF_INET;
  72.  local.sin_port := htons(5150);
  73.  local.sin_addr.S_addr := inet_addr('127.0.0.1');
  74.   //将socket绑定地址
  75.  nError := bind(soRecv,local,sizeof(local));
  76.  if nError = SOCKET_ERROR then
  77.      CheckRc('bind');
  78.  //分配内存
  79.  pszRecv := AllocMem(4096);
  80.  
  81.  for i := 0 to dwCount -1 do
  82.  begin
  83.      dwSenderSize := SizeOf(siSender);
  84.     //接收发送过来的数据,并保存到缓冲区中
  85.     nRet := recvFrom(soRecv,pszRecv[0],4096,0,siSender,dwSenderSize);
  86.  
  87.     if nRet = SOCKET_ERROR then
  88.     begin
  89.            CheckRc('recvFrom');
  90.       break;
  91.     end else if nRet = 0 then
  92.            break
  93.     else
  94.     begin
  95.            pszRecv[nRet] := #0;
  96.       //添加到列表中,仅用于显示
  97.       self.ListBox1.Items.Add(pszRecv);
  98.     end;
  99.     Inc(nNumOfRecv);
  100.     self.Edit1.Text := IntToStr(nNumOfRecv);
  101.  
  102.  end//end of for
  103.  //关闭 socket
  104.  closesocket(soRecv);
  105.  //释放分配的内存
  106.  FreeMem(pszRecv);
  107.  //清理winsocket
  108.  WSACleanup();
  109. end;
  110.  
  111. end.