WinSock编程基础

本文介绍了Windows Sockets(WinSock)编程的基础知识,包括WinSock涉及的驱动、套接字描述符、Windows Sockets规范以及套接字通信的基础。详细讲解了套接字地址结构、字节顺序转换函数、IP地址处理以及TCP/IP的连接与关闭。通过示例展示了WinSock在C/S通信中的应用。
摘要由CSDN通过智能技术生成
一.套接字的一些基础知识

1Windows通信相关驱动

netio.sys(Network I/O Subsystem)

ndis.sys(NDIS Driver)

ipnat.sys(IP Network Address Translator)

tcpip.sys(TCP/IP Driver)

tdtcp.sys(TCP Transport Driver)

tdi.sys(TDI wrapper)

afd.sys(Ancillary Function Driver for Winsock)

http.sys(HTTP Protocol Stack)

……

2socket描述符(套接字句柄)

UNIX系统中,任何东西都是一个文件。这句话描述了这样一个事实:在UNIX系统中,任何对I/O的操作,都是通过读或写一个文件描述符(File DescriptorFile了到对方发送的数据Port+Length+Checksum)来实现的。

一个文件描述符(FD)只是一个简单的整形数值,代表一个被打开的文件(这里的文件是广义的文件,并不只是代表不同的磁盘文件,它可以代表一个网络上的连接,一个先进先出的队列,一个终端显示屏等)。

既然在UNIX系统中任何东西都是一个文件,通过Internet和另外一台机器进行通讯也是基于文件描述符来实现的。这个文件描述符即套接字内核对象:intsockfd。在早期的UNIX/Linux系统中,可调用read()write()直接对套接字进行类似文件的读写操作,尽管调用recv()send()显得更为专业。

Windoze系统中,内核对象往往交由一个句柄与外部交互,如文件句柄。在很多WinSock场合我们习惯使用套接字句柄这一称呼:typedefu_intSOCKET。实际上,WinSock中对于套接字的操作,很多也沿袭了文件操作的规范。例如,在Winsock 1中,应用程序可以针对套接字句柄调用ReadFile()WriteFile(),同时指定重叠结构以利用重叠I/O模型,到Winsock 2中才正式替换为WSARecv()WSASend(),以专用于套接字操作。

3Windows Sockets规范

Sockets本来是UNIX操作系统下流行的一种网络编程接口(API),它是1983年在Berkeley(加州大学伯克利分校)4.2 BSD操作系统中被首先引入的,因此被称为“Berkeley Socket API”

Windows Sockets是在Windows环境下使用的一套网络编程规范,常常简称为WinSock。在Winsock规范中把Winsock API函数集分为与BSD Socket(用在UNIX)相兼容的基本函数、网络数据信息检索函数和Windows专用扩展函数三类。

Windows Socket 1规范的核心内容是符合Berkeley Socket风格的库函数,例如可以编写基于select模型的的socket跨平台库。select模型可以很好地实现跨平台,但对具体操作系统平台而言,并非性能最佳的I/O模型。为了使程序员能充分利用Windows消息驱动机制进行编程,又定义开发了一组针对Windows的扩展库函数,这就是Windows Socket 2规范。Winsock 2.x提供了基于Windows消息机制的WSAAsyncSelcet异步I/O网络事件通知模型,除此之外WinSock 2.x还提供了基于事件通知的异步I/O网络事件通知的WSAEventSelect模型和高效的重叠I/O模型。具体平台实现了各自高效的网络I/O管理模型,例如Windoze的IOCP模型、Linux的epoll模型,它们用来实现大规模高并发的通信应用程序。

目前常用的Winsock有两个版本:一个是16位的Winsock 1.1,由动态链接库WINSOCK.DLL提供支持;另一个是32位的Winsock 2.2,由动态链接库WSOCK32.DLL提供支持。

Win98/NT4开始,Windows支持WinSock 2,WinSock 1成为WinSock 2的功能子集。在32位系统下,16位的WINSOCK.DLL(Windows Socket 16-bit DLL)Non-resident

ws2_32.dllmswsock.dllWinSock 2真正的实现者。wsock32.dll只是映射了ws2_32.Dllmswsock.dll两个文件的一些函数调用,并无具体实现。使用Dependency Walker可以看到wsock32.dllmswsock.dll都依赖ws2_32.dll

mswsock.dll提供了微软特有的WSA扩展,包括AcceptEx/GetAcceptExSockaddrsConnectEx/DisconnectExTransmitPackets/TransmitFileWSARecvMsg。其中仅有AcceptEx/GetAcceptExSockaddrsTransmitFile这三个函数真正从mswsock.dll导出。

如果要求编写符合Berkeley Socket API标准的程序,则只需要加载wsock32.dll使用WinSock 1.x规范(BSD Socket API for Wndows)就可以了。如果要结合Windows平台特性编写WinSock 2.x的程序,则可加载ws2_32.dllmswsock.dll调用WSA系列(扩展)函数。加载WinSock库是通过WSAStartup()来指定的。

1)加载WinSock 1.1

/* WINSOCK.H--definitions to be used with the WINSOCK.DLL

* Copyright (c) Microsoft Corporation. All rights reserved.

*

* This header file corresponds to version 1.1 of the Windows Sockets specification.

*

* (1)Basic system type definitions, taken from the BSD file sys/types.h.

* (2)Structure used in select() call, taken from the BSD file sys/time.h.

* (3)Commands for ioctlsocket(), taken from the BSD file fcntl.h.

* (4)Structures returned by network data base library, taken from the BSD file netdb.h.

* (5)Constants and structures defined by the internet system, Per RFC 790, September 1981, taken from the BSD file netinet/in.h.

* (6)Definitions related to sockets: types, address families, options, taken from the BSD file sys/socket.h.

*

* (7)Microsoft Windows Extension function prototypesWSA开头的WSAStartupWSACleanupWindows Sockets API

* (8)Microsoft Windows Extended data typestypedefSOCKADDRSOCKADDR_IN等宏

*/

#include<WinSock.h>

#pragmacomment(lib,"WSock32.Lib")

LoadLibrary("C://WINDOWS//system32/wsock32.dll");// Windows Socket 32-Bit DLL

Windows Mobile下对应winsock.h/winsock.lib/winsock.dll

2)加载WinSock 2.2

/* Winsock2.h -- definitions to be used with the WinSock 2 DLL and

*              WinSock 2 applications.

*

* This header file corresponds to version 2.2.x of the WinSock API

* specification.

*

* #define _WINSOCKAPI_  // Prevent inclusion of winsock.h in windows.h

*/

#include<WinSock2.h>

#pragmacomment(lib,"WS2_32.lib")

LoadLibrary("C://WINDOWS//system32//ws2_32.dll");// Windows Socket 2.0 32-Bit DLL

Windows Mobile下对应winsock2.h/ws2.lib/ws2.dll

3)加载Microsoft Windows-Specific Extension Functions

/*++

Module Name:

mswsock.h

Abstract:

This module contains the Microsoft-specific extensions to the Windows Sockets API.

--*/

#include<Mswsock.h>

#pragmacomment(lib,"MsWSock.Lib")

LoadLibrary("C://WINDOWS//system32//mswsock.dll");// Microsoft Windows Socket 2.0 Service Provider

二.套接字通信基础

至此,我还不打算直接进入套接字的一些诸如recv()和send()操作。在正式使用套接字进行通信编程之前,有必要先了解一下通信所涉及到地址识别、字节顺序等知识点。

1.套接字地址(sockaddr)、TCP/IP套接字地址(sockaddr_in)和IP地址in_addr

1.1 structsockaddr

structsockaddr结构用来存储套接字地址。

/*

* Structure used by kernel to store most addresses.

*/

structsockaddr {

u_shortsa_family;/* address family,AF_X */

char   sa_data[14];/* up to 14 bytes of direct address */

};

sa_data包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂溶在一起的。sa_data域的定义有些不确定性,注释暗示内容可能超过14个字节。这种不确定性是经过深思熟虑的。套接字是个非常强大的接口。多数人可能认为比Internet接口强不到哪里——大多数应用现在很可能都用它——套接字可被用于几乎任何种类的进程间通信,Internet(更精确的说是IP只是其支持的协议簇中的一种。

#defineSOCK_MAXADDRLEN 255    /*可能的最长的地址长度*/

socket层涉及到地址的API都是用sockaddr结构,这些API包括bind(服务器绑定本地地址+端口)、connect(连接服务器)/accept(接受客户端)、recvfrom/sendto

intbind(intsockfd, structsockaddr *my_addr,intaddrlen);

intaccept(intsockfd, structsockaddr *addr,int*addrlen);

intconnect(intsockfd, const structsockaddr *serv_addr,intaddrlen);

1.2 structsockaddr_in

Sockets API提供了structsockaddrTCP/IP版本——structsockaddr_in,其中in代表“internet”,故sockaddr_in.sa_family=AF_INET

/*

* Socket address, internet style.

*/

structsockaddr_in {

short sin_family;/* internet address family */

u_shortsin_port;/* port number */

struct in_addrsin_addr;/* internet address */

charsin_zero[8];/* padding bits */

};

这个结构提供了方便的手段来访问socket addressstructsockaddr)结构中的每一个元素。注意sin_zero[8]是为了使sockaddrsockaddr_in结构具有相同的尺寸,使用sockaddr_in的时候要把

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值