第一步:the wsastartup function initiates use of ws2_32.dll by a process.
在所有 windows sockets 函数中,只有启动函数 wsastartup() 和终止函数 wsacleanup() 是必须使用的。
启动函数必须是第一个使用的函数,而且它允许指定 windows sockets api 的版本,并获得 sockets的特定的一些技术细节。本结构如下:
int pascal far wsastartup(word wversionrequested, lpwsadata lpwsadata);
其中 wversionrequested 保证 sockets 可正常运行的 dll 版本,如果不支持,则返回错误信息。
我们看一下下面这段代码,看一下如何进行 wsastartup() 的调用
word wversionrequested;// 定义版本信息变量
wsadata wsadata;//定义数据信息变量
int err;//定义错误号变量
wversionrequested = makeword(1,1);//给版本信息赋值
err = wsastartup(wversionrequested, &wsadata);//给错误信息赋值
if(err!=0)
{
return;//告诉用户找不到合适的版本
}
//确认 windows sockets dll 支持 1.1 版本
//dll 版本可以高于 1.1
//系统返回的版本号始终是最低要求的 1.1,即应用程序与dll 中可支持的最低版本号
if(lobyte(wsadata.wversion)!= 1|| hibyte(wsadata.wversion)!=1)
{
wsacleanup();//告诉用户找不到合适的版本
return;
}
//windows sockets dll 被进程接受,可以进入下一步操作
关闭函数使用时,任何打开并已连接的 sock_stream 套接字被复位,但那些已由 closesocket() 函数关闭的但仍有未发送数据的套接字不受影响,未发送的数据仍将被发送。程序运行时可能会多次调用 wsastartuo() 函数,但必须保证每次调用时的 wversionrequested 的值是相同的。
第二步:在初始化了wsastartup后建立socket
msdn:the socket function creates a socket that is bound to a specific service provider.
初始化winsock的动态连接库后,需要在服务器端建立一个监听的socket,为此可以调用socket()函数用来建立这个监听的socket,并定义此socket所使用的通信协议。此函数调用成功返回socket对象,失败则返回invalid_socket(调用wsagetlasterror()可得知原因,所有winsocket 的函数都可以使用这个函数来获取失败的原因)。
socket pascal far socket( int af, int type, int protocol )
参数: af:目前只提供 pf_inet(af_inet);
type:socket 的类型 (sock_stream、sock_dgram);
protocol:通讯协定(如果使用者不指定则设为0);
如果要建立的是遵从tcp/ip协议的socket,第二个参数type应为sock_stream,如为udp(数据报)的socket,应为sock_dgram。
第三步:绑定(服务器端需要)
msdn:the bind function associates a local address with a socket.
为服务器端定义的这个监听的socket指定一个地址及端口(port),这样客户端才知道待会要连接哪一个地址的哪个端口,为此我们要调用bind()函数,该函数调用成功返回0,否则返回socket_error。
int pascal far bind( socket s, const struct sockaddr far *name,int namelen );
参 数: s:socket对象名;
name:socket的地址值,这个地址必须是执行这个程式所在机器的ip地址;
namelen:name的长度;
如果使用者不在意地址或端口的值,那么可以设定地址为inaddr_any,及port为0,windows sockets 会自动将其设定适当之地址及port (1024 到 5000之间的值)。此后可以调用getsockname()函数来获知其被设定的值。
上面那个socketaddr是这样定义的:the sockaddr structure varies depending on the protocol selected. except for the sin*_family parameter, sockaddr contents are expressed in network byte order.
这个结构经常被
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};所代替
in_addr是一个联合体
定义如下
typedef 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;
} in_addr;