| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 987 人关注过本帖
标题:htons()返回不同值的问题
只看楼主 加入收藏
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10757
专家分:43344
注 册:2014-5-20
收藏
得分:0 
按htons的定义返回的是16位无符号整数。
上面的例子36895应该才是对的,用在BINTOC函数时要判断转换为16位有符号整数。
昨天 09:37
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
应该是我理解错了,还是要经过htons()的转换
不过咱们应用环境比较固定,vfp9,所以bintoc(nPort-2^15,"2r")也算正确吧

[此贴子已经被作者于2025-10-8 10:16编辑过]

昨天 10:01
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10757
专家分:43344
注 册:2014-5-20
收藏
得分:0 
不用htons()也可以,就是大小端转换,即16位的低8位与高8位互换。
用VFP的位运算函数就可以。
昨天 10:20
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
回复 23楼 吹水佬
bintoc函数中的参数“R”可以实现自动翻转功能
昨天 10:21
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
SET CENTURY on
SET DATE ANSI
SET HOURS TO 24
CLEAR

fh=_GetNetTime("128.138.140.44",13)
?zh(fh)
retu
retu

FUNCTION _GetNetTime(szNtpIP, ddNtpPort)
LOCAL stWsaData, stSockAddr, szBuffer, dhSocket
LOCAL i, ddLen,ret

DECLARE LONG WSAStartup  IN "Ws2_32" LONG, STRING@
DECLARE LONG WSACleanup  IN "Ws2_32"
DECLARE LONG socket      IN "Ws2_32" LONG, LONG, LONG
DECLARE LONG connect     IN "Ws2_32" LONG, STRING@, LONG
DECLARE LONG recv        IN "Ws2_32" LONG, STRING@, LONG, LONG
DECLARE LONG closesocket IN "Ws2_32" LONG
DECLARE LONG inet_addr   IN "Ws2_32" STRING@
DECLARE LONG htons       IN "Ws2_32" LONG
DECLARE INTEGER gethostbyname in WSOCK32 String@
DECLARE LONG inet_ntoa     IN "Ws2_32" LONG

stWsaData  = REPLICATE(0h00, 398)
szBuffer   = REPLICATE(0h00, 256)
stSockAddr = REPLICATE(0h00, 16)

WSAStartup(0x202, @stWsaData)
dhSocket = socket(2, 1, 6)
IF ISDIGIT(szNtpIP)
    stSockAddr = 0h0200;
        + BINTOC(htons(ddNtpPort), "2RS");
        + BINTOC(inet_addr(@szNtpIP), "4RS");
        + REPLICATE(0h00, 8)
else
    RET = CTOBIN(SYS(2600, gethostbyname(@szNtpIP) + 12, 4), "4RS")  &&偏移12,IP地址列表
    RET = CTOBIN(SYS(2600, RET, 4), "4RS")  &&IP地址
    stSockAddr = 0h0200;
        + BINTOC(htons(ddNtpPort), "2RS");
        + SYS(2600, RET, 4);
        + REPLICATE(0h00, 8)
endif
ddLen  = 0
IF connect(dhSocket, @stSockAddr, LEN(stSockAddr)) = -1
    ?"连接失败"
else
    FOR i = 1 TO 3
        ddLen = recv(dhSocket, @szBuffer, LEN(szBuffer), 0)
        IF ddLen != -1
            EXIT
        ENDIF
    ENDFOR
endif
closesocket(dhSocket)
WSACleanup()
IF ddLen > 0
    szBuffer = LEFT(szBuffer, ddLen)
    RETURN szBuffer
ELSE
*        MESSAGEBOX("网络异常,时间同步失败")
    RETURN ""
ENDIF
ENDFUNC

PROCEDURE zh
LPARAMETERS szutc
IF EMPTY(szutc)
else
    ddYear   = INT(VAL(SUBSTR(szUTC, 8, 2))) + 2000
    ddMonth  = INT(VAL(SUBSTR(szUTC, 11, 2)))
    ddDay    = INT(VAL(SUBSTR(szUTC, 14, 2)))
    ddHour   = INT(VAL(SUBSTR(szUTC, 17, 2)))
    ddMinute = INT(VAL(SUBSTR(szUTC, 20, 2)))
    ddSecond = INT(VAL(SUBSTR(szUTC, 23, 2)))
    RETURN DATETIME(ddYear,ddMonth,ddDay,ddHour,ddMinute,ddSecond)+8*3600
endif
RETURN ""
获取网络时间,代码都是从网上抄的,又随意改的,测试htons,发现用bintoc(nPort-2^15,"2")才是正确的
因为这里经过htons转换后又加了个参数r,搞不懂了
stSockAddr = 0h0200;
        + BINTOC(htons(ddNtpPort), "2RS");
        + BINTOC(inet_addr(@szNtpIP), "4RS");
        + REPLICATE(0h00, 8)
只能这样改
stSockAddr = 0h0200;
        + BINTOC(ddNtpPort-2^15, "2");
        + BINTOC(inet_addr(@szNtpIP), "4RS");
        + REPLICATE(0h00, 8)


[此贴子已经被作者于2025-10-8 10:55编辑过]

昨天 10:53
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
通过ntp获取时间,网上说端口是123,可我测试发现只有端口13才可以获取,123却连接失败
这几个都可以获取网络时间,但端口都是13才可以
"time-a.nist.gov"
"time-b.nist.gov"
"128.138.140.44"
昨天 15:20
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
这个是udp协议,最后接收失败,没有调试成功,通过NTP获取网络时间
    DECLARE INTEGER WSAGetLastError IN ws2_32
   
    * 初始化Winsock
    DECLARE INTEGER WSAStartup IN ws2_32 INTEGER, STRING @
    DECLARE INTEGER WSACleanup IN ws2_32
   
    lcWSAData = REPLI(CHR(0), 400)
    IF WSAStartup(0x202, @lcWSAData) != 0
        ? "Winsock初始化失败"
        RETURN
    ENDIF
   
    * 创建UDP Socket
    DECLARE INTEGER socket IN ws2_32 INTEGER, INTEGER, INTEGER
    DECLARE INTEGER closesocket IN ws2_32 INTEGER
   
    lnSocket = socket(2, 2, 17)  && AF_INET, SOCK_DGRAM, IPPROTO_UDP
    IF lnSocket = -1
        ? "Socket创建失败: " + TRANSFORM(WSAGetLastError())
        WSACleanup()
        RETURN
    ENDIF
   
    * 设置超时
    DECLARE INTEGER setsockopt IN ws2_32 INTEGER, INTEGER, INTEGER, STRING @, INTEGER
    lcTimeout = num2dword(5000)  && 5秒超时
    setsockopt(lnSocket, 0xFFFF, 0x1006, @lcTimeout, 4)  && SO_RCVTIMEO
   
    * 构建NTP请求
    lcNTPData = CHR(0x1B) + REPLI(CHR(0), 47)
   
    * 发送到NTP服务器
    DECLARE INTEGER sendto IN ws2_32 INTEGER, STRING @, INTEGER, INTEGER, STRING @, INTEGER
    DECLARE INTEGER inet_addr IN ws2_32 STRING
    DECLARE short htons       IN "Ws2_32" short
   
    lnServerIP = inet_addr("120.25.115.20")  && 阿里云NTP服务器IP
   
    lcSockAddr = 0h0200+ num2word(123)+num2dword(lnServerIP) + REPLI(CHR(0), 8)
    IF sendto(lnSocket, @lcNTPData, 48, 0, @lcSockAddr, 16) = -1
        ? "发送失败: " + TRANSFORM(WSAGetLastError())
        closesocket(lnSocket)
        WSACleanup()
        RETURN
    ENDIF
   
    ? "请求发送成功,等待响应..."
   
    * 接收响应
    DECLARE INTEGER recvfrom IN ws2_32 INTEGER, STRING @, INTEGER, INTEGER, STRING @, INTEGER @
   
    lcBuffer = REPLI(CHR(0), 1024)
    lcFromAddr = REPLI(CHR(0), 16)
    lnAddrLen = 16
   
    lnReceived = recvfrom(lnSocket, @lcBuffer, 1024, 0, @lcFromAddr, @lnAddrLen)
    IF lnReceived >= 48
        ? "收到响应,长度: " + TRANSFORM(lnReceived)
        * 解析时间...
    ELSE
        ? "接收失败: " + TRANSFORM(WSAGetLastError())
    ENDIF
   
    closesocket(lnSocket)
    WSACleanup()

FUNCTION num2dword(lnValue)
    LOCAL lcResult, i
    lcResult = ""
    FOR i = 3 TO 0 STEP -1
        lcResult = lcResult + CHR(BITRSHIFT(lnValue, i*8) % 256)
    ENDFOR
    RETURN lcResult
ENDFUNC

FUNCTION num2word(lnValue)
    RETURN CHR(BITRSHIFT(lnValue, 8) % 256) + CHR(lnValue % 256)
ENDFUNC
昨天 17:09
sam_jiang
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:14
帖 子:992
专家分:1516
注 册:2021-10-13
收藏
得分:0 
回复 25楼 sych
你这段代码htons函数声明不对,和我一样申明为long或integer了!
昨天 17:14
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
回复 28楼 sam_jiang
都是网上抄的代码,不知其所以然,不过可以运行一下代码试试,先调试通过再修改BUG
昨天 17:23
sych
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:438
专家分:670
注 册:2019-10-11
收藏
得分:0 
DECLARE INTEGER WSAGetLastError IN ws2_32

* 初始化Winsock
DECLARE INTEGER WSAStartup IN ws2_32 INTEGER, STRING @
DECLARE INTEGER WSACleanup IN ws2_32

lcWSAData = REPLI(CHR(0), 400)
IF WSAStartup(0x202, @lcWSAData) != 0
    ? "Winsock初始化失败"
    RETURN
ENDIF

* 创建UDP Socket
DECLARE INTEGER socket IN ws2_32 INTEGER, INTEGER, INTEGER
DECLARE INTEGER closesocket IN ws2_32 INTEGER

lnSocket = socket(2, 2, 17)  && AF_INET, SOCK_DGRAM, IPPROTO_UDP
IF lnSocket = -1
    ? "Socket创建失败: " + TRANSFORM(WSAGetLastError())
    WSACleanup()
    RETURN
ENDIF
* 设置超时
DECLARE INTEGER setsockopt IN ws2_32 INTEGER, INTEGER, INTEGER, STRING @, INTEGER
lcTimeout = BINTOC(5000,"4s")  && 5秒超时
setsockopt(lnSocket, 0xFFFF, 0x1006, @lcTimeout, 4)  && SO_RCVTIMEO
* 构建NTP请求
lcNTPData = CHR(0x1B) + REPLI(CHR(0), 47)

* 发送到NTP服务器
DECLARE INTEGER sendto IN ws2_32 INTEGER, STRING @, INTEGER, INTEGER, STRING @, INTEGER
DECLARE INTEGER inet_addr IN ws2_32 STRING

lnServerIP = inet_addr("120.25.115.20")  && 阿里云NTP服务器IP
*lnServerIP = inet_addr("202.120.2.101")  &&国家授时中心

lcSockAddr = 0h0200+ bintoc(123,"2s")+bintoc(lnServerIP-2^31,"4r") + REPLI(CHR(0), 8)
IF sendto(lnSocket, @lcNTPData, 48, 0, @lcSockAddr, 16) = -1
    ? "发送失败: " + TRANSFORM(WSAGetLastError())
    closesocket(lnSocket)
    WSACleanup()
    RETURN
ENDIF

? "请求发送成功,等待响应..."

* 接收响应
DECLARE INTEGER recvfrom IN ws2_32 INTEGER, STRING @, INTEGER, INTEGER, STRING @, INTEGER @

lcBuffer = REPLI(CHR(0), 1024)
lcFromAddr = REPLI(CHR(0), 16)
lnAddrLen = 16
lnReceived = recvfrom(lnSocket, @lcBuffer, 1024, 0, @lcFromAddr, @lnAddrLen)
IF lnReceived >= 48
    ? "收到响应,长度: " + TRANSFORM(lnReceived)
    lnTransmitSec = ctobin(SUBSTR(lcBuffer, 41, 4))+2^31
    lnTransmitFrac = (ctobin(SUBSTR(lcBuffer, 45, 4))+2^31)/4294967296
    ?DATETIME(1970,1,1,0,0,0)+lnTransmitSec-2208988800+8*60*60
ELSE
    ? "接收失败: " + TRANSFORM(WSAGetLastError())
ENDIF
closesocket(lnSocket)
WSACleanup()
retu
调试通过

[此贴子已经被作者于2025-10-8 22:11编辑过]

昨晚 21:05
快速回复:htons()返回不同值的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019371 second(s), 10 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved