设计一个基本的网络服务器有以下几个步骤:
1、初始化Windows Socket
2、创建一个监听的Socket
3、设置服务器地址信息,并将监听端口绑定到这个地址上
4、开始监听
5、接受客户端连接
6、和客户端通信
7、结束服务并清理Windows Socket和相关数据,或者返回第4步
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模型,因为它比较简单,而且有一定的实用性。但是,几乎所有人都认识到,要开发同时响应成千上万用户的网络程序,完成端口模型是最好的选择。
是不是看始记我所说的模型了?呵呵,不慌!我们先看看做一简单的网络程序所需要的知识!
1.WSADATA 数据类型
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
} WSADATA, FAR * LPWSADATA;
下面我们将就其中的参数进行一下分析:
wVersion:为动态链接库ws2_32.dll将要使用的版本;
wHighVersion:为该动态链接库所支持的window Socket的最高版本;
szDescription:Window Socket的实现描述.
szSystemStatus:系统的相关状态和配置信息。
后面三项只是为了与Window Socket保持一定的兼容性。
2.SOCKET数据类型
每一个MFC Socket对象都包含了一指针,该指针指向了Windows的Socket对象。该指针的数据类型是SOCKET。
3.SOCKADDR_IN数据类型
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
4.WSAStartup函数
int WSAStartup (
WORD wVersionRequested, 调用者所能使用的wondwo socket最高版本
LPWSADATA lpWSAData 为输出
);
注意:在一个应用程序或者动态链接库中,该函数是第一个被调用的Window Socket函数。通过使用该函数,程序或者动态链接库可以确定使用window Socket的哪个版本并且得到该版本的具体实现细节。只有在该函数被成功调用后,我们才能进一步使用其它windwo socket函数。
5.htons函数
u_short htons( u_short hostshort)将主机上的u_short类型变量转化为tcp/ip网络的字节顺序
6.htons函数
u_long htonl (u_long hostlong );将主机上的u_long类型转化为tcp/ip网络的字节顺序
7..socket函数
SOCKET socket (
int af, 地址的类型
int type, 新socket的类型。在socket1.1版本里面有两种类型:socket_stream和socket_dgram。
在socket2里面有许多新的类型而且不需要在这里进行确定。应用程序可以通过WSAEnumProtocls函数动态的发现可用传输协议的属性。
int protocol 确定将使用什么协议,该协议与指定的地址类相对应。
8..bind函数
int bind ( 该函数为绑定监听端口
SOCKET s, 一个没有被绑定的socket
const struct sockaddr FAR* name, socketaddr结构的地址
int namelen 名字的长度
);
.