
Windows 网络编程 Ares.vip.myrice.com
Windows 网络编程
快乐魔导师
Ares.vip.myrice.com
QQ: 35830152
E-Mail: euho@sina.com

Windows 网络编程
第一章 序言
我写这个专题的目的,一方面是为了通过对网络编程再一次系统的总结,提高自己的
网络编程水平,特别是 Windows 下的网络编程水平。同时,我也希望,能为众多初学网络
编程的人提供一点帮助,因为我开始学习网络编程的时候,能找到的资料就很少。当然,
花钱可以买到翻译版本的书:)
首先向大家推荐一本很好的参考书,Network Programming for Microsoft Windows 2
nd
,
初学网络编程的时候我还不知道有这样一本好书,只是上各大论坛把能找到的网络编程方
面的文章和代码下载下来,然后自己研究。后来看到别人推荐这一本书,下载了一个,看
了感觉非常好,里面的内容写得很规范,条理也很清楚,英文好的朋友可以直接阅读,不
然就只好去弄一本翻译好的来研究了。、
我试着从 Windows 编程的基础开始,一直到探索建立高性能的网络应用程序。我说过,
我并不是以高手的身份写这本书,而是以和大家一起学习的心态学习网络编程,写书只是
让自己的思路更清晰,以后还可以翻阅。所以,我不保证书中所有的内容都是绝对正确和
标准的,有不妥的地方,还希望高手批评指正。
这本书是完全免费的,读者可以任意使用书中的代码。但是如果需要转载,请注明原
作者和出处。如果有商业运作的需求,请直接和我联系。
第二章 Windows 网络编程基础
这本书主要探索 Windows 网络编程,开发平台是 Windows 2000 和 Visual C++.NET,
从一个合格的 C++程序员到网络编程高手,还是需要花不少功夫,至少我认为写一个聊天
程序很简单,而要写一个能同时响应成千上万用户的高性能网络程序,的确不容易。这篇
文章所介绍的方法也并不是能直接应用于每一个具体的应用程序,只能作为学习的参考资
料。
开发高性能网络游戏恐怕是促使很多程序员研究网络编程的原因(包括我),现在的
大型网络游戏对同时在线人数的要求比较高,真正的项目往往采取多个服务器(组)负荷
分担的方式工作,我将首先把注意力放到单个服务器的情况。
大家都知道,我们用得最多的协议是 UDP 和 TCP,UDP 是不可靠传输服务,TCP 是
可靠传输服务。UDP 就像点对点的数据传输一样,发送者把数据打包,包上有收信者的地
址和其他必要信息,至于收信者能不能收到,UDP 协议并不保证。而 TCP 协议就像(实际
他们是一个层次的网络协议)是建立在 UDP 的基础上,加入了校验和重传等复杂的机制来
保证数据可靠的传达到收信者。关于网络协议的具体内容,读者可以参考专门介绍网络协
议的书籍,或者查看 RFC 中的有关内容。本书直接探讨编程实现网络程序的问题。
2

快乐魔导师 Ares.vip.myrice.com
2.1 Window Socket 介绍
Windows Socket 是从 UNIX Socket 继承发展而来,最新的版本是 2.2。进行 Windows 网
络编程,你需要在你的程序中包含 WINSOCK2.H 或 MSWSOCK.H,同时你需要添加引入
库 WS2_32. LIB 或 WSOCK32.LIB。准备好后,你就可以着手建立你的第一个网络程序了。
Socket 编 程有阻塞 和 非 阻 塞 两 种 ,在操作 系 统 I/O 实 现时又有 几 种 模 型 ,包括
Select,WSAAsyncSelect,WSAEventSelect ,IO 重叠模型,完成端口等。要学习基本的网
络编程概念,可以选择从阻塞模式开始,而要开发真正实用的程序,就要进行非阻塞模式
的编程(很难想象一个大型服务器采用阻塞模式进行网络通信)。在选择 I/O 模型时,我
建议初学者可以从 WSAAsyncSelect 模型开始,因为它比较简单,而且有一定的实用性。
但是,几乎所有人都认识到,要开发同时响应成千上万用户的网络程序,完成端口模型是
最好的选择。
既然完成端口模型是最好的选择,那为什么我们不直接写出一个使用完成端口的程序,
然后大家稍加修改就 OK 了。我认为这确实是一个好的想法,但是真正做项目的时候,不
同的情况对程序有不同的要求,如果不深入学习网络编程的各方面知识,是不可能写出符
合要求的程序,在学习网络编程以前,我建议读者先学习一下网络协议。
2.2 第一个网络程序
由于服务器/客户端模式的网络应用比较多,而且服务器端的设计是重点和难点。所以
我想首先探讨服务器的设计方法,在完成服务器的设计后再探讨其他模式的网络程序。
设计一个基本的网络服务器有以下几个步骤:
1、初始化 Windows Socket
2、创建一个监听的 Socket
3、设置服务器地址信息,并将监听端口绑定到这个地址上
4、开始监听
5、接受客户端连接
6、和客户端通信
7、结束服务并清理 Windows Socket 和相关数据,或者返回第 4 步
我们可以看出设计一个最简单的服务器并不需要太多的代码,它完全可以做一个小型
的聊天程序,或进行数据的传输。但是这只是我们的开始,我们的最终目的是建立一个有
大规模响应能力的网络服务器。如果读者对操作系统部分的线程使用还有疑问,我建议你
现在就开始复习,因为我们经常使用线程来提高程序性能,其实线程就是让 CPU 不停的工
作,而不是总在等待 I/O,或者是一个 CPI,累死了还是一个 CPU。千万不要以为线程越多
的服务器,它的性能就越好,线程的切换也是需要消耗时间的,对于 I/O 等待少的程序,
线程越多性能反而越低。
下面是简单的服务器和客户端源代码。(阻塞模式下的,供初学者理解)
3

Windows 网络编程
TCPServer
#include <winsock2.h>
void main(void)
{
WSADATA wsaData;
SOCKET ListeningSocket;
SOCKET NewConnection;
SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;
int Port = 5150;
// 初始化 Windows Socket 2.2
WSAStartup(MAKEWORD(2,2), &wsaData);
// 创建一个新的 Socket 来响应客户端的连接请求
ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 填写服务器地址信息
// 端口为 5150
// IP 地址为 INADDR_ANY,注意使用 htonl 将 IP 地址转换为网络格式
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定监听端口
bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr));
// 开始监听,指定最大同时连接数为 5
listen(ListeningSocket, 5);
// 接受新的连接
NewConnection = accept(ListeningSocket, (SOCKADDR *)
&ClientAddr,&ClientAddrLen));
4

快乐魔导师 Ares.vip.myrice.com
// 新的连接建立后,就可以互相通信了,在这个简单的例子中,我们直接关闭连接,
// 并关闭监听 Socket,然后退出应用程序
//
closesocket(NewConnection);
closesocket(ListeningSocket);
// 释放 Windows Socket DLL 的相关资源
WSACleanup();
}
TCPClient
# include <winsock2.h>
void main(void)
{
WSADATA wsaData;
SOCKET s;
SOCKADDR_IN ServerAddr;
int Port = 5150;
//初始化 Windows Socket 2.2
WSAStartup(MAKEWORD(2,2), &wsaData);
// 创建一个新的 Socket 来连接服务器
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 填写客户端地址信息
// 端口为 5150
// 服务器 IP 地址为"136.149.3.29",注意使用 inet_addr 将 IP 地址转换为网络格式
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.s_addr = inet_addr("136.149.3.29");
// 向服务器发出连接请求
connect(s, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr));
5
评论1