程序采用udp socket进行通信,用winsock api函数实现,C/S结构。C给S发来数据包,如何实现在S端从这个包中取C端的IP和主机名?getpeername()好像只支持面向连接的socket.
    如上述实现不了,我准备这样做:先在C端直接得到C的IP和主机名,然后再直接发给S,S收到这个包再取出,不知这样行不?有更直接的方法吗?
    先谢了!!!

解决方案 »

  1.   

    int recvfrom (    SOCKET s,
        char FAR* buf,
        int len,
        int flags,
        struct sockaddr FAR* from,
        int FAR* fromlen
       );其中from这个sockaddr包含了发送段工作站的地址
      

  2.   

    可以使用inet_ntoa把sockaddr结构中的sin_addr解析为IP地址给你写了一个简单的例子,用1.1版winsock api实现的,代码临时写的,有点乱。unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,WinSock, Sockets;type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
      TThreadRead=class(TThread)
        private
          FK :TSocket;
          fbuf : array[0..255] of char;
          add : TSockAddrIn;
          procedure GetInfo;    public
          constructor Create(sock : TSocket);
          procedure Execute;override;
      end;var
      Form1: TForm1;
      SSock : TSocket;
      WSAData : TWSAData;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
      ErrorCode : integer;
      SockAdd_In : TSockAddrIn;
    begin
      //创建一个“服务器”段,其实就是用来接受数据的
      SSock := socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if SSock = SOCKET_ERROR then
      begin
        showmessage(Format('%s;ErrorCode:%d',['½¨Á¢Ì×½Ó×Öʧ°Ü',WSAGetLastError]) );
        Exit;
      end;  SockAdd_In.sin_family := PF_INET;
      SockAdd_In.sin_port := htons(5150);
      SockAdd_In.sin_addr.S_addr := htonl(INADDR_ANY);
      //绑定
      ErrorCode := bind(SSock,SockAdd_In,sizeof(SockAdd_In));
      if ErrorCode = SOCKET_ERROR then
      begin
        showmessage(Format('%s;ErrorCode:%d',['°ó¶¨Ì×½Ó×Öʧ°Ü',WSAGetLastError]) );
        Exit;
      end;
      //建立一个读线程用来读取数据
      TThreadRead.Create(SSock); // FAcceptSockThread := TAcceptSockThread.Create(FSock);
    end;{ TThreadRead }constructor TThreadRead.Create(sock: TSocket);
    begin
      FK := sock;
      inherited Create(false);
    end;procedure TThreadRead.Execute;
    var
      tm : integer;
    begin
      while not terminated do
      begin
        tm := sizeof(add);
        if recvfrom(FK,fbuf,256,0,add,tm) > 0 then
        begin
          Synchronize(GetInfo);
          Sleep(0);
        end;  end;
    end;procedure TThreadRead.GetInfo;
    var
     s : string;
    begin
       s := fbuf;
       s := s+#13 + inet_ntoa(add.sin_addr);
       Form1.Memo1.Lines.Add(s);
    end;procedure StartUp;
    var
      ErrorCode : integer;
    begin
      ErrorCode := WSAStartup($0101, WSAData);
      if ErrorCode <> 0 then
      begin
        ShowMessage('&frac14;&Oacute;&Ocirc;&Oslash;&Ecirc;§°&Uuml;');
        exit;
      end;
    end;
    //发送端
    procedure TForm1.Button2Click(Sender: TObject);
    var
      ErrorCode : integer;
      buf : array[0..255] of Char;
      SockAddTo : TSockAddrIn;
      SkC : TSocket;
    begin  skc := socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if skc = SOCKET_ERROR then
      begin
        showmessage('加载失败);
        Exit;
      end;  SockAddTo.sin_family := PF_INET;
      SockAddTo.sin_port := htons(5150);
      SockAddTo.sin_addr.S_addr := inet_addr('192.168.1.3');  buf :='wudi_1982';
      sendto(SkC,buf,256*sizeof(char),0,SockAddTo,sizeof(SockAddTo));  closesocket(skc);end;initialization
      StartUp;
    finalization
      WSACleanup;end.
      

  3.   

    谢谢yudi_1982朋友的指点,s := s+#13 + inet_ntoa(add.sin_addr)可以得到发送方的地址(我现在只在同一台电脑上用127.0.0.1试了一下还行,稍后再分别用两台电脑试)。
        这种方法可以得到发送方的IP,但是发送方的主机名还是通过数据包主动发给接收方的:
        buf :='wudi_1982';
        sendto(SkC,buf,256*sizeof(char),0,SockAddTo,sizeof(SockAddTo));
    还有其他的方法吗?能直接得到发送方的主机名的?