`
isiqi
  • 浏览: 16487769 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论
阅读更多
WinSock介绍

Windows下网络编程的规范-Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口。从1991年的1.0版到1995年的2.0.8版,经过不断完善并在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的全力支持下,已成为Windows网络编程的事实上的标准。

Windows Sockets规范以U.C. Berkeley大学BSD UNIX中流行的Socket接口为范例定义了一套Micosoft Windows下网络编程接口。它不仅包含了人们所熟悉的Berkeley Socket风格的库函数;也包含了一组针对Windows的扩展库函数,以使程序员能充分地利用Windows消息驱动机制进行编程。Windows Sockets规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。此外,在一个特定版本Windows的基础上,Windows Sockets也定义了一个二进制接口(ABI),以此来保证应用Windows Sockets API的应用程序能够在任何网络软件供应商的符合Windows Sockets协议的实现上工作。因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。遵守这套Windows Sockets规范的网络软件,我们称之为Windows Sockets兼容的,而Windows Sockets兼容实现的提供者,我们称之为Windows Sockets提供者。一个网络软件供应商必须百分之百地实现Windows Sockets规范才能做到现Windows Sockets兼容。任何能够与Windows Sockets兼容实现协同工作的应用程序就被认为是具有Windows Sockets接口。我们称这种应用程序为Windows Sockets应用程序。Windows Sockets规范定义并记录了如何使用API与Internet协议族(IPS,通常我们指的是TCP/IP)连接,尤其要指出的是所有的Windows Sockets实现都支持流套接口和数据报套接口.应用程序调用Windows Sockets的API实现相互之间的通讯。Windows Sockets又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。它们之间的关系

通信的基础是套接口(Socket),一个套接口是通讯的一端。在这一端上你可以找到与其对应的一个名字。一个正在被使用的套接口都有它的类型和与其相关的进程。套接口存在于通讯域中。通讯域是为了处理一般的线程通过套接口通讯而引进的一种抽象概念。套接口通常和同一个域中的套接口交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。Windows Sockets规范支持单一的通讯域,即Internet域。各种进程使用这个域互相之间用Internet协议族来进行通讯(Windows Sockets 1.1以上的版本支持其他的域,例如Windows Sockets 2)。套接口可以根据通讯性质分类;这种性质对于用户是可见的。应用程序一般仅在同一类的套接口间通讯。不过只要底层的通讯协议允许,不同类型的套接口间也照样可以通讯。用户目前可以使用两种套接口,即流套接口和数据报套接口。流套接口提供了双向的,有序的,无重复并且无记录边界的数据流服务。数据报套接口支持双向的数据流,但并不保证是可靠,有序,无重复的。也就是说,一个从数据报套接口接收信息的进程有可能发现信息重复了,或者和发出时的顺序不同。数据报套接口的一个重要特点是它保留了记录边界。对于这一特点,数据报套接口采用了与现在许多包交换网络(例如以太网)非常类似的模型。

一个在建立分布式应用时最常用的范例便是客户机/服务器模型。在这种方案中客户应用程序向服务器程序请求服务。这种方式隐含了在建立客户机/服务器间通讯时的非对称性。客户机/服务器模型工作时要求有一套为客户机和服务器所共识的惯例来保证服务能够被提供(或被接受)。这一套惯例包含了一套协议。它必须在通讯的两头都被实现。根据不同的实际情况,协议可能是对称的或是非对称的。在对称的协议中,每一方都有可能扮演主从角色;在非对称协议中,一方被不可改变地认为是主机,而另一方则是从机。一个对称协议的例子是Internet中用于终端仿真的TELNET。而非对称协议的例子是Internet中的FTP。无论具体的协议是对称的或是非对称的,当服务被提供时必然存在"客户进程"和"服务进程"。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。在这个时刻,服务程序被"惊醒"并且为客户提供服务-对客户的请求作出适当的反应。这一请求/相应的过程可以简单的表示。虽然基于连接的服务是设计客户机/服务器应用程序时的标准,但有些服务也是可以通过数据报套接口提供的。

数据报套接口可以用来向许多系统支持的网络发送广播数据包。要实现这种功能,网络本身必须支持广播功能,因为系统软件并不提供对广播功能的任何模拟。广播信息将会给网络造成极重的负担,因为它们要求网络上的每台主机都为它们服务,所以发送广播数据包的能力被限制于那些用显式标记了允许广播的套接口中。广播通常是为了如下两个原因而使用的:1. 一个应用程序希望在本地网络中找到一个资源,而应用程序对该资源的地址又没有任何先验的知识。2. 一些重要的功能,例如路由要求把它们的信息发送给所有可以找到的邻机。被广播信息的目的地址取决于这一信息将在何种网络上广播。Internet域中支持一个速记地址用于广播-INADDR_BROADCAST。由于使用广播以前必须捆绑一个数据报套接口,所以所有收到的广播消息都带有发送者的地址和端口。

Intel处理器的字节顺序是和DEC VAX处理器的字节顺序一致的。因此它与68000型处理器以及Internet的顺序是不同的,所以用户在使用时要特别小心以保证正确的顺序。任何从Windows Sockets函数对IP地址和端口号的引用和传送给Windows Sockets函数的IP地址和端口号均是按照网络顺序组织的,这也包括了sockaddr_in结构这一数据类型中的IP地址域和端口域(但不包括sin_family域)。考虑到一个应用程序通常用与"时间"服务对应的端口来和服务器连接,而服务器提供某种机制来通知用户使用另一端口。因此getservbyname()函数返回的端口号已经是网络顺序了,可以直接用来组成一个地址,而不需要进行转换。然而如果用户输入一个数,而且指定使用这一端口号,应用程序则必须在使用它建立地址以前,把它从主机顺序转换成网络顺序(使用htons()函数)。相应地,如果应用程序希望显示包含于某一地址中的端口号(例如从getpeername()函数中返回的),这一端口号就必须在被显示前从网络顺序转换到主机顺序(使用ntohs()函数)。由于Intel处理器和Internet的字节顺序是不同的,上述的转换是无法避免的,应用程序的编写者应该使用作为Windows Sockets API一部分的标准的转换函数,而不要使用自己的转换函数代码。因为将来的Windows Sockets实现有可能在主机字节顺序与网络字节顺序相同的机器上运行。因此只有使用标准的转换函数的应用程序是可移植的。

在MFC中MS为套接口提供了相应的类CAsyncSocket和CSocket,CAsyncSocket提供基于异步通信的套接口封装功能,CSocket则是由CAsyncSocket派生,提供更加高层次的功能,例如可以将套接口上发送和接收的数据和一个文件对象(CSocketFile)关联起来,通过读写文件来达到发送和接收数据的目的,此外CSocket提供的通信为同步通信,数据未接收到或是未发送完之前调用不会返回。此外通过MFC类开发者可以不考虑网络字节顺序和忽略掉更多的通信细节。

在一次网络通信/连接中有以下几个参数需要被设置:本地IP地址 - 本地端口号 - 对方端口号 - 对方IP地址。左边两部分称为一个半关联,当与右边两部分建立连接后就称为一个全关联。在这个全关联的套接口上可以双向的交换数据。如果是使用无连接的通信则只需要建立一个半关联,在发送和接收时指明另一半的参数就可以了,所以可以说无连接的通信是将数据发送到另一台主机的指定端口。此外不论是有连接还是无连接的通信都不需要双方的端口号相同。

在创建CAsyncSocket对象时通过调用
BOOL CAsyncSocket::Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddress = NULL )通过指明lEvent所包含的标记来确定需要异步处理的事件,对于指明的相关事件的相关函数调用都不需要等待完成后才返回,函数会马上返回然后在完成任务后发送事件通知,并利用重载以下成员函数来处理各种网络事件: 标记 事件 需要重载的函数
FD_READ 有数据到达时发生 void OnReceive( int nErrorCode );
FD_WRITE 有数据发送时产生void OnSend( int nErrorCode );
FD_OOB 收到外带数据时发生 void OnOutOfBandData( int nErrorCode );
FD_ACCEPT 作为服务端等待连接成功时发生 void OnAccept( int nErrorCode );
FD_CONNECT 作为客户端连接成功时发生 void OnConnect( int nErrorCode );
FD_CLOSE 套接口关闭时发生 void OnClose( int nErrorCode );
我们看到重载的函数中都有一个参数nErrorCode,为零则表示正常完成,非零则表示错误。通过int CAsyncSocket::GetLastError()可以得到错误值。


下面我们看看套接口类所提供的一些功能,通过这些功能我们可以方便的建立网络连接和发送数据。

BOOL CAsyncSocket::Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddress = NULL );用于创建一个本地套接口,其中nSocketPort为使用的端口号,为零则表示由系统自动选择,通常在客户端都使用这个选择。nSocketType为使用的协议族,SOCK_STREAM表明使用有连接的服务,SOCK_DGRAM表明使用无连接的数据报服务。lpszSocketAddress为本地的IP地址,可以使用点分法表示如10.1.1.3。
BOOL CAsyncSocketBind( UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL )作为等待连接方时产生一个网络半关联,或者是使用UDP协议时产生一个网络半关联。
BOOL CAsyncSocketListen( int nConnectionBacklog = 5 )作为等待连接方时指明同时可以接受的连接数,请注意不是总共可以接受的连接数。
BOOL CAsyncSocket::Accept( CAsyncSocket& rConnectedSocket, SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL )作为等待连接方将等待连接建立,当连接建立后一个新的套接口将被创建,该套接口将会被用于通信。
BOOL CAsyncSocket::Connect( LPCTSTR lpszHostAddress, UINT nHostPort );作为连接方发起与等待连接方的连接,需要指明对方的IP地址和端口号。
void CAsyncSocket::Close( );关闭套接口。
int CAsyncSocket::Send( const void* lpBuf, int nBufLen, int nFlags = 0 )
int CAsyncSocket::Receive( void* lpBuf, int nBufLen, int nFlags = 0 );在建立连接后发送和接收数据,nFlags为标记位,双方需要指明相同的标记。
int CAsyncSocket::SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress = NULL, int nFlags = 0 )
int CAsyncSocket::ReceiveFrom( void* lpBuf, int nBufLen, CString& rSocketAddress, UINT& rSocketPort, int nFlags = 0 );对于无连接通信发送和接收数据,需要指明对方的IP地址和端口号,nFlags为标记位,双方需要指明相同的标记。
我们可以看到大多数的函数都返回一个布尔值表明是否成功。如果发生错误可以通过int CAsyncSocket::GetLastError()得到错误值。

由于CSocket由CAsyncSocket派生所以拥有CAsyncSocket的所有功能,此外你可以通过BOOL CSocket::Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, LPCTSTR lpszSocketAddress = NULL )来创建套接口,这样创建的套接口没有办法异步处理事件,所有的调用都必需完成后才会返回。

在上面的介绍中我们看到MFC提供的套接口类屏蔽了大多数的细节,我们只需要做很少的工作就可以开发出利用网络进行通信的软件。
分享到:
评论

相关推荐

    网络编程WinSock基础

    WinSock基础知识点 WinSock基础知识点主要包括套接字基本概念、WinSock编程原理、WinSock I/O模型、WinSock 2的扩展特性、套接字选项和I/O控制命令等。 1. 套接字基本概念 套接字是网络通信的基本构件,是可以被...

    网络编程教程之winsock基础

    网络编程教程之 Winsock 基础 Winsock 是 Windows 操作系统中的网络编程接口,提供了一个通用的网络编程模型,允许开发者创建高效、可靠的网络应用程序。本教程将prehensive 介绍 Winsock 的基础知识,让学习者快速...

    Windows网络编程第二版\07-Winsock基础.pdf

    ### Windows网络编程第二版之Winsock基础 #### 一、Winsock概述 在《Windows网络编程第二版》这本书中,第7章详细介绍了Winsock的基础知识。Winsock是一种API(应用程序接口),它允许应用程序通过TCP/IP协议进行...

    Windows网络编程技术_Winsock基础(资料+源码)

    第7章 Winsock基础 1327.1 Winsock的初始化 1327.2 错误检查和控制 1347.3 面向连接的协议 1347.3.1 服务器API函数 1347.3.2 客户机API函数 1387.3.3 数据传输 1407.3.4 流协议 1447.3.5 中断连接 1467.3.6 综合分析...

    winsock 基础教程

    《Winsock基础教程》 Winsock是Windows操作系统中用于网络通信的一个API,它提供了与Berkeley Sockets类似的接口,使得开发者能在Windows环境下进行网络编程。本文将深入介绍Winsock的基础知识,包括TCP/IP协议下的...

    winsock例程 一个winsock的简单例程,适合新手

    1. **Winsock基础** - **定义**: Winsock是Windows操作系统中的网络编程接口,遵循Berkeley Sockets API,允许开发者创建TCP/IP协议的应用程序。 - **作用**: 它为Windows上的各种网络应用程序提供底层通信服务,...

    winsock编程 c#实现

    1. **Winsock基础**: Winsock,全称Windows Socket,是Windows操作系统中的网络编程接口,它提供了与Berkeley Sockets类似的API,使得开发者可以在Windows上进行TCP/IP通信。Winsock库包含了一系列函数,用于创建...

    WinSock编程规范及应用

    1. **WinSock基础知识** - **定义**:WinSock是Windows环境下的一组API,它提供了与Berkeley Sockets类似的接口,使得开发者能够在Windows系统上编写网络应用程序。 - **版本**:WinSock分为Winsock 1.1和Winsock ...

    Winsock编程

    1. **Winsock基础知识** Winsock,全称为"Windows Sockets",是微软为Windows操作系统提供的网络编程接口。它遵循了Berkeley Sockets API标准,使得开发者能够在Windows平台上实现跨平台的网络应用。Winsock提供了...

    winsock相关编程源代码

    1. **Winsock基础** - **初始化**:在使用Winsock进行编程时,首先需要调用`WSAStartup`函数来初始化Winsock库。 - **套接字创建**:通过`socket`函数创建套接字,指定协议类型(如TCP或UDP)、地址家族(如AF_...

    基于WINSOCK的WEB SERVER

    1. WINSOCK基础:WINSOCK是Windows上的网络编程接口,遵循Berkeley Sockets接口规范,用于提供TCP/IP协议的支持。它允许程序员直接操作网络层,如TCP、UDP等传输协议,实现客户端和服务器之间的数据交换。 2. VS...

    winsock教程1

    一、Winsock基础 1.1 Winsock概述 Winsock是基于Berkeley Sockets接口的,它允许开发者使用标准的Socket API进行网络通信。这个API包含了创建套接字、绑定、监听、连接、发送和接收数据等函数,使得程序员可以轻松...

    WinSock windows 下sock编程

    一、WinSock基础知识 WinSock是Windows操作系统对Berkeley Sockets接口的实现,它为开发人员提供了一套跨平台的网络编程接口。在使用WinSock前,需要通过`WSAStartup`函数初始化WinSock库,并在程序结束时调用`...

    WinSock编程基础讲义

    **WinSock编程基础** WinSock,也称为Windows Socket API,是微软为Windows操作系统提供的网络通信接口,它使得程序员能够利用TCP/IP协议栈进行网络编程。本文将深入讲解WinSock编程的基础,包括流式套接字和数据报...

    winsock详细api手册

    1. **Winsock基础** - **初始化和终止**:在使用Winsock API前,必须先调用`WSAStartup`进行初始化,结束后则使用`WSACleanup`。这两个函数确保Winsock库的正确加载和释放。 - **套接字创建**:`socket`函数用于...

    WINSOCK多线程传输文件

    **Winsock基础知识** Winsock是Windows平台上的网络编程接口,它为开发者提供了标准的API,用于创建基于TCP/IP协议的应用程序。通过Winsock,程序员可以构建各种网络应用,如聊天软件、邮件客户端、文件传输等。主要...

    通过winsock实现客户端向服务器端传输文件

    一、Winsock基础 Winsock是Windows系统提供的一个标准接口,它允许程序员编写跨平台的网络应用程序。Winsock库包含了多种网络协议,如TCP、UDP等,使得开发者可以构建基于这些协议的网络通信程序。要使用Winsock,...

    Winsock_Test

    **Winsock基础知识** 1. **API接口**: Winsock API提供了一系列的函数,如`socket()`, `bind()`, `listen()`, `accept()`, `connect()`, `send()`, 和`recv()`等,用于创建套接字、绑定端口、监听连接、接受连接、...

    Winsock编写的TCP聊天

    1. **Winsock基础** - Winsock是微软对Berkeley套接字API的实现,用于在Windows上进行网络通信。 - 它提供了标准的函数调用,如`socket()`、`bind()`、`listen()`、`accept()`、`connect()`、`send()`和`recv()`等...

    基于winsock的聊天室设计

    1. **Winsock基础**: - Winsock初始化:在使用Winsock进行编程时,首先要调用`WSAStartup`函数来初始化Winsock库。 - Winsock版本:确保选择正确的Winsock版本,通常是2.2或更高版本。 - 结构体`sockaddr_in`:...

Global site tag (gtag.js) - Google Analytics