zoukankan      html  css  js  c++  java
  • 网络高手看过来:为什么我用htons转换网络节序时会发生错误?200元大洋伺候

    来源:http://www.delphibbs.com/delphibbs/dispq.asp?lid=2190549

    procedure TForm1.Button1Click(Sender: TObject);
    type TDebugDL = record
       Parm1:String;
       Parm2:String;
       Parm3:String;
       Parm4:String;
       Parm5:String;
       Parm6:String;
       Parm7:String;
    end;
    var
       FSyn_Buf: array[0..2] of char;
       TheStream: TWinSocketStream;
       ClientSocket: TClientSocket;
       iPkglen: integer;
       iTotalPkg: Word;
       DebugDL: TDebugDL;
    begin
    DebugDL.Parm1:=Format('%-6s',['010200']);
    DebugDL.Parm2:=Format('%-6s',['335615']);
    DebugDL.Parm3:=Format('%-10s',['100120130']);
    DebugDL.Parm4:=Format('%-8s',['']);
    DebugDL.Parm5:=Format('%-2s',['']);
    DebugDL.Parm6:=Format('%-2s',['02']);
    DebugDL.Parm7:=Format('%-5s',['96528']);
    FSyn_Buf[0] := #2;
    FSyn_Buf[1] := #0;
    FSyn_Buf[2] := #0;
    iPkglen:= sizeof(DebugDL);                  //数据包长度
    iTotalPkg:= htons(word(iPkglen));   <font color=red>(*为什么运行到这句要发生错误*)</font>
    //建立连接
    ClientSocket:= TClientSocket.Create(nil);
    TheStream:= TWinSocketStream.Create(ClientSocket.Socket,6000);
    ClientSocket.ClientType:= ctBlocking;
    ClientSocket.Address:= '172.16.2.1';
    ClientSocket.Port :=3000;
    ClientSocket.Open;
    TheStream.Write(FSyn_Buf,4);                 //发包头
    TheStream.Write(iTotalPkg,2);                //发长度
    //  TheStream.Write(htons(iTotalPkg),2);       //发内容
    FillChar(Buffer1, 5, 0);
    if TheStream.WaitForData(6000) then begin
       TheStream.Read(Buffer1,4);
       for i:=0 to 5-1 do  //前4位是包的长度
         strRec:=strRec+Buffer1[i];
       showmessage(strRec);
    end;
    end;


    计算机处理器有两种排序方式:big-endian和little-endian。
    intel86处理器用little-endian:字节的排序是从最无意义的字节到最有意义的字节。称为“主机字节顺序”。
    在网络上指定IP地址和端口号,必须用big-endian来表示:从最有意义的字节到最无意义的字节。一般称之为“网络字节顺序”。
    主机字节顺序与网络字节顺序的转换函数:
    u_long htonl(u_long hostlogn);
    int WSAHtonl(
    SOCKET s,
    u_long hostlogn,
    u_long FAR * lpnetlong
    );
    u_short htons(u_short hostshort);
    int WSAHtons(
    SOCKET s,
    u_short hostshort,
    u_short FAR * lpnetshort
    );
    htonl和WSAHtonl的hostlong参数是按主机字节顺序排序的一个4字节数。
    htonl函数返回的数网络字节顺序,WSAHtonl函数通过lpnetlogn参数返回网络字节顺序排序数。用于IP地址转换。
    htons和WSAHtons的hostshort参数是按主机字节顺序排序的一个2字节数。用于端口转换。
    htons函数把这个hostshort参数当作按网络字节排序的一个2字节数返回,而WSAHtons函数则通过lpnetshort参数返回。
    下面4个函数是前4个函数的逆向函数,它们把网络字节顺序转换成主机字节顺序:
    u_long ntohl(u_long netlong);
    int WSANtohl(
    SOCKET s,
    u_long netlog,
    u_long FAR * lphostlong
    );
    u_short ntohs(u_short netshort);
    int WSANtohs(
    SOCKET s,
    u_short netshort,
    u_short FAR * lphostshort
    );
    例:
    var
    InternetAddr: TSockAddrIn;
    const
    nProtId = 5150; //端口号。主机字节顺序排序格式
    cp = '136.149.3.29'; //IP地址。点分internet地址格式
    begin
    {使用IP地址族}
    InternetAddr.sin_family := AF_INET;
    {将cp转换为4字节整数,并把它分配给sin_addr}
    InternetAddr.sin_addr.S_addr := inet_addr(cp);
    {将字段转换为网络字节顺序,并分配给sin_port}
    InternetAddr.sin_port := htons(nProtId);
    end;


    来自: Another_eYes, 时间: 2003-09-22 7:56:00, ID: 2191192 
    应当没有错的,最多出来一个warning(也许你的哪个编译开关不对所以无法运行?)。
    因为Integer->Word强制类型转换可能造成数据失真。用iTotalPkg:= htons(word(Cardinal(iPkglen)))试试。

    说句题外话:
    iPkglen:= sizeof(DebugDL);                  //数据包长度
    这句没有意义,因为iPkglen永远等于28(不管你param1~param7中有没有数据也不管你那里面的数据是什么)

    来自: youjq, 时间: 2003-09-22 14:39:00, ID: 2192327 
    TO:Another_eYes
    我试过加Cardinal也没用,运行到Htons这句时屏幕就会弹出一个错误框好象
    是什么内存地址出错什么的,是系统的。还有其他办法吗?


    来自: youjq, 时间: 2003-09-22 18:16:00, ID: 2193094 
    问题解决了,原因是我 use  了idwinsocket 应该use winsocket就对了

  • 相关阅读:
    支付
    mui自定义事件带参返回mui.back()
    tomcat+nginx反向代理(实现一个服务器,一个ip共用80端口)
    mui.back()返回刷新功能
    WiFi(网络)调试Android手机
    mysql获取外键, 根据数据库名和表名获取表所对应的所有外键
    @RequestBody接收json字符串,自动将日期字符串转换为java.util.Date
    使用MySQLWorkBench绘制ER图
    jpa动态分页查找
    displaytag的Excel导出实践
  • 原文地址:https://www.cnblogs.com/railgunman/p/1885959.html
Copyright © 2011-2022 走看看