先写了个简单的功能,一旦建立连接则显示connected,在虚拟机上测试通过!
下一步实验发送和接收信息。
几番测试达不到预期的收发效果。我开始怀疑虚拟机网络搭建得是否到位。于是互ping了一下,果真不通,一番折腾最后发现是虚拟机的系统自带防火墙没关…
最终测试结果:不管在bridge模式还是NAT模式下,都可以达到两机互ping。
然后我用经典的《帝国时代2》来做测试,因为这游戏带有现在都不怎么见到了的tcp/ip互联功能。
测试结果为:
桥接模式下,局域网和tcp/ip模式都可正常使用。
NAT模式下,局域网模式正常,tcp/ip只能在虚拟机建主,而虚拟机检测不到物理机的主机。
这样一来,网络测试环境毋庸置疑了。
因为没有一个好用的printf()函数,程序到底卡在哪一步很难判断。而网络通讯这玩意来来回回的,很需要有效的调试手段,一开始我是在每次大循环的刷新画面时设置很多标志开关来显示信息,不过有时程序也许会卡在某处根本运行不到刷新画面那一步。
虽然可以换到控制台去练习掌握,不过我还是决定,自己做一个好用的print函数,可以方便的在窗口中打印出文本。一开始以为会比较难,冷静下来琢磨FontPrint()函数后,我发现只要注意此函数必须在d3ddev->BeginScene()和d3ddev->EndScene()间调用这一点,就可以简单的做出能随时使用的Print()。
另外要注意d3ddev及d3ddev->BeginScene()并非总是有效,所以教材中都加了if来判断,假如不加,有时就会打印失败。所以我用每次都循环打印5遍来解决╮(╯_╰)╭。这样必然效率很低而且理论上讲5次都碰到设备未准备好的几率也是存在的,不管了,以后再寻求更好的办法吧。
(2013.8.12注:如前所述,《游戏编程入门》源码的谬误导致这个bug,根本不需要循环多遍,后面会阐述正确的解决办法)
一番下来,客户端会显示send successful了,而主机仍旧接收不到。必然是对某个函数未理解清楚。
我按教程代码加进了很多错误判断,这样错误就有迹可循了,发现问题主要出在主机accept时发生了10014错误。
网上查了下,说加一句ClientAddrLen = sizeof(ClientAddr);就没问题了。
本来完全不相信,结果一试,竟然成功了!
我很不解,教材源代码中也没加ClientAddrLen = sizeof(ClientAddr)啊,难道是大神在误人子弟?决定在控制台下测试下。
源代码直接编译是通不过的,必须加入ws2_32.lib文件或是用pragma包含。
debug模式下编译出的tcpclient.exe会提示找不到msvcr90d.dll,这是一个bug…,换release模式就行了。
在控制台里敲命令行来执行程序,最方便的方法是把exe文件放到cmd默认路径下执行。
在每个return之前加getchar()能保证窗口不一闪而过。
最终我发现一个不争的事实,大神书中的源代码也有经不起考验的!假如不加那句,程序运行就会出10014错误。
另外要先建立好服务端,再运行客户端,不然connect会返回错误。这说明我反复connect的写法倒是好用一些。
最后总算实现了send和receive,算是阶段性突破。总结几点:
1,客户端connect及send成功与否,与服务端是否成功accept及receive是无关联的。
2,accept()函数第三个长度参数要事先赋值。
3,经典教材中的源代码也是会有错误的,不能盲目遵从。
(2013.8.12注:截止今日共发现三本教材都包含小错误,甚至包括《windows游戏编程大师技巧》、《windows网络编程》这种经典,这个世界到处都是坑啊!)