




已阅读5页,还剩109页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
WinSock网络编程实用宝典 一、TCP/IP 体系结构与特点 1、TCP/IP体系结构TCP/IP协议实际上就是在物理网上的一组完整的网络协议。其中TCP是提供传输层服务,而IP则是提供网络层服务。TCP/IP包括以下协议:(结构如图1.1)(图1.1) IP: 网间协议(Internet Protocol) 负责主机间数据的路由和网络上数据的存储。同时为ICMP,TCP,UDP提供分组发送服务。用户进程通常不需要涉及这一层。 ARP: 地址解析协议(Address Resolution Protocol) 此协议将网络地址映射到硬件地址。 RARP: 反向地址解析协议(Reverse Address Resolution Protocol) 此协议将硬件地址映射到网络地址 ICMP: 网间报文控制协议(Internet Control Message Protocol) 此协议处理信关和主机的差错和传送控制。 TCP: 传送控制协议(Transmission Control Protocol) 这是一种提供给用户进程的可靠的全双工字节流面向连接的协议。它要为用户进程提供虚电路服务,并为数据可靠传输建立检查。(注:大多数网络用户程序使用TCP) UDP: 用户数据报协议(User Datagram Protocol) 这是提供给用户进程的无连接协议,用于传送数据而不执行正确性检查。 FTP: 文件传输协议(File Transfer Protocol) 允许用户以文件操作的方式(文件的增、删、改、查、传送等)与另一主机相互通信。 SMTP: 简单邮件传送协议(Simple Mail Transfer Protocol) SMTP协议为系统之间传送电子邮件。 TELNET:终端协议(Telnet Terminal Procotol) 允许用户以虚终端方式访问远程主机 HTTP: 超文本传输协议(Hypertext Transfer Procotol) TFTP: 简单文件传输协议(Trivial File Transfer Protocol) 2、TCP/IP特点 TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现。因此用户一般不涉及。编程时,编程界面有两种形式:一、是由内核心直接提供的系统调用;二、使用以库函数方式提供的各种函数。前者为核内实现,后者为核外实现。用户服务要通过核外的应用程序才能实现,所以要使用套接字(socket)来实现。 图1.2是TCP/IP协议核心与应用程序关系图。 (图1.2)二、专用术语 1、套接字 套接字是网络的基本构件。它是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连听进程。套接字存在通信区域(通信区域又称地址簇)中。套接字只与同一区域中的套接字交换数据(跨区域时,需要执行某和转换进程才能实现)。WINDOWS 中的套接字只支持一个域网际域。套接字具有类型。 WINDOWS SOCKET 1.1 版本支持两种套接字:流套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM) 2、WINDOWS SOCKETS 实现 一个WINDOWS SOCKETS 实现是指实现了WINDOWS SOCKETS规范所描述的全部功能的一套软件。一般通过DLL文件来实现 3、阻塞处理例程 阻塞处理例程(blocking hook,阻塞钩子)是WINDOWS SOCKETS实现为了支持阻塞套接字函数调用而提供的一种机制。 4、多址广播(multicast,多点传送或组播) 是一种一对多的传输方式,传输发起者通过一次传输就将信息传送到一组接收者,与单点传送 (unicast)和广播(Broadcast)相对应。 一、客户机/服务器模式 在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model)。该模式的建立基于以下两点:1、非对等作用;2、通信完全是异步的。客户机/服务器模式在操作过程中采取的是主动请示方式: 首先服务器方要先启动,并根据请示提供相应服务:(过程如下) 1、打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求。 2、等待客户请求到达该端口。 3、接收到重复服务请求,处理该请求并发送应答信号。 4、返回第二步,等待另一客户请求 5、关闭服务器。 客户方: 1、打开一通信通道,并连接到服务器所在主机的特定端口。 2、向服务器发送服务请求报文,等待并接收应答;继续提出请求 3、请求结束后关闭通信通道并终止。 二、基本套接字 为了更好说明套接字编程原理,给出几个基本的套接字,在以后的篇幅中会给出更详细的使用说明。 1、创建套接字socket() 功能:使用前创建一个新的套接字 格式:SOCKET PASCAL FAR socket(int af,int type,int procotol); 参数:af: 通信发生的区域 type: 要建立的套接字类型 procotol: 使用的特定协议 2、指定本地地址bind() 功能:将套接字地址与所创建的套接字号联系起来。 格式:int PASCAL FAR bind(SOCKET s,const struct sockaddr FAR * name,int namelen); 参数:s: 是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。 其它:没有错误,bind()返回0,否则SOCKET_ERROR 地址结构说明: struct sockaddr_in short sin_family;/AF_INET u_short sin_port;/16位端口号,网络字节顺序 struct in_addr sin_addr;/32位IP地址,网络字节顺序 char sin_zero8;/保留 3、建立套接字连接connect()和accept() 功能:共同完成连接工作 格式:int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen); SOCKET PASCAL FAR accept(SOCKET s,struct sockaddr FAR * name,int FAR * addrlen); 参数:同上 4、监听连接listen() 功能:用于面向连接服务器,表明它愿意接收连接。 格式:int PASCAL FAR listen(SOCKET s, int backlog); 5、数据传输send()与recv() 功能:数据的发送与接收 格式:int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags); int PASCAL FAR recv(SOCKET s,const char FAR * buf,int len,int flags); 参数:buf:指向存有传输数据的缓冲区的指针。 6、多路复用select() 功能:用来检测一个或多个套接字状态。 格式:int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds, fd_set FAR * exceptfds,const struct timeval FAR * timeout); 参数:readfds:指向要做读检测的指针 writefds:指向要做写检测的指针 exceptfds:指向要检测是否出错的指针 timeout:最大等待时间 7、关闭套接字closesocket() 功能:关闭套接字s 格式:BOOL PASCAL FAR closesocket(SOCKET s); 三、典型过程图 2.1 面向连接的套接字的系统调用时序图 2.2 无连接协议的套接字调用时序图 2.3 面向连接的应用程序流程图 Windows Socket1.1 程序设计 一、简介 Windows Sockets 是从 Berkeley Sockets 扩展而来的,其在继承 Berkeley Sockets 的基础上,又进行了新的扩充。这些扩充主要是提供了一些异步函数,并增加了符合WINDOWS消息驱动特性的网络事件异步选择机制。 Windows Sockets由两部分组成:开发组件和运行组件。 开发组件:Windows Sockets 实现文档、应用程序接口(API)引入库和一些头文件。 运行组件:Windows Sockets 应用程序接口的动态链接库(WINSOCK.DLL)。 二、主要扩充说明 1、异步选择机制: Windows Sockets 的异步选择函数提供了消息机制的网络事件选择,当使用它登记网络事件发生时,应用程序相应窗口函数将收到一个消息,消息中指示了发生的网络事件,以及与事件相关的一些信息。 Windows Sockets 提供了一个异步选择函数 WSAAsyncSelect(),用它来注册应用程序感兴趣的网络事件,当这些事件发生时,应用程序相应的窗口函数将收到一个消息。 函数结构如下: int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent);参数说明: hWnd:窗口句柄 wMsg:需要发送的消息 lEvent:事件(以下为事件的内容) 值:含义:FD_READ期望在套接字上收到数据(即读准备好)时接到通知FD_WRITE期望在套接字上可发送数据(即写准备好)时接到通知FD_OOB期望在套接字上有带外数据到达时接到通知FD_ACCEPT期望在套接字上有外来连接时接到通知FD_CONNECT期望在套接字连接建立完成时接到通知FD_CLOSE期望在套接字关闭时接到通知例如:我们要在套接字读准备好或写准备好时接到通知,语句如下: rc=WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE);如果我们需要注销对套接字网络事件的消息发送,只要将 lEvent 设置为0 2、异步请求函数 在 Berkeley Sockets 中请求服务是阻塞的,WINDOWS SICKETS 除了支持这一类函数外,还增加了相应的异步请求函数(WSAAsyncGetXByY();)。 3、阻塞处理方法 Windows Sockets 为了实现当一个应用程序的套接字调用处于阻塞时,能够放弃CPU让其它应用程序运行,它在调用处于阻塞时便进入一个叫“HOOK”的例程,此例程负责接收和分配WINDOWS消息,使得其它应用程序仍然能够接收到自己的消息并取得控制权。 WINDOWS 是非抢先的多任务环境,即若一个程序不主动放弃其控制权,别的程序就不能执行。因此在设计Windows Sockets 程序时,尽管系统支持阻塞操作,但还是反对程序员使用该操作。但由于 SUN 公司下的 Berkeley Sockets 的套接字默认操作是阻塞的,WINDOWS 作为移植的 SOCKETS 也不可避免对这个操作支持。 在Windows Sockets 实现中,对于不能立即完成的阻塞操作做如下处理:DLL初始化循环操作。在循环中,它发送任何 WINDOWS 消息,并检查这个 Windows Sockets 调用是否完成,在必要时,它可以放弃CPU让其它应用程序执行(当然使用超线程的CPU就不会有这个麻烦了_)。我们可以调用 WSACancelBlockingCall() 函数取消此阻塞操作。 在 Windows Sockets 中,有一个默认的阻塞处理例程 BlockingHook() 简单地获取并发送 WINDOWS 消息。如果要对复杂程序进行处理,Windows Sockets 中还有 WSASetBlockingHook() 提供用户安装自己的阻塞处理例程能力;与该函数相对应的则是 SWAUnhookBlockingHook(),它用于删除先前安装的任何阻塞处理例程,并重新安装默认的处理例程。请注意,设计自己的阻塞处理例程时,除了函数 WSACancelBlockingHook() 之外,它不能使用其它的 Windows Sockets API 函数。在处理例程中调用 WSACancelBlockingHook()函数将取消处于阻塞的操作,它将结束阻塞循环。 4、出错处理 Windows Sockets 为了和以后多线程环境(WINDOWS/UNIX)兼容,它提供了两个出错处理函数来获取和设置当前线程的最近错误号。(WSAGetLastEror()和WSASetLastError()) 5、启动与终止 使用函数 WSAStartup() 和 WSACleanup() 启动和终止套接字。 三、Windows Sockets网络程序设计核心 我们终于可以开始真正的 Windows Sockets 网络程序设计了。不过我们还是先看一看每个 Windows Sockets 网络程序都要涉及的内容。让我们一步步慢慢走。1、启动与终止 在所有 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 的值是相同的。2、异步请求服务 Windows Sockets 除支持 Berkeley Sockets 中同步请求,还增加了了一类异步请求服务函数 WSAAsyncGerXByY()。该函数是阻塞请求函数的异步版本。应用程序调用它时,由 Windows Sockets DLL 初始化这一操作并返回调用者,此函数返回一个异步句柄,用来标识这个操作。当结果存储在调用者提供的缓冲区,并且发送一个消息到应用程序相应窗口。常用结构如下: HANDLE taskHnd; char hostname=rs6000; taskHnd = WSAAsyncBetHostByName(hWnd,wMsg,hostname,buf,buflen); 需要注意的是,由于 Windows 的内存对像可以设置为可移动和可丢弃,因此在操作内存对象是,必须保证 WIindows Sockets DLL 对象是可用的。 3、异步数据传输 使用 send() 或 sendto() 函数来发送数据,使用 recv() 或recvfrom() 来接收数据。Windows Sockets 不鼓励用户使用阻塞方式传输数据,因为那样可能会阻塞整个 Windows 环境。下面我们看一个异步数据传输实例: 假设套接字 s 在连接建立后,已经使用了函数 WSAAsyncSelect() 在其上注册了网络事件 FD_READ 和 FD_WRITE,并且 wMsg 值为 UM_SOCK,那么我们可以在 Windows 消息循环中增加如下的分支语句: case UM_SOCK: switch(lParam) case FD_READ: len = recv(wParam,lpBuffer,length,0); break; case FD_WRITE: while(send(wParam,lpBuffer,len,0)!=SOCKET_ERROR) break; break; 4、出错处理 Windows 提供了一个函数来获取最近的错误码 WSAGetLastError(),推荐的编写方式如下: len = send (s,lpBuffer,len,0); of(len=SOCKET_ERROR)&(WSAGetLastError()=WSAWOULDBLOCK). 基于Visual C+的Winsock API研究 为了方便网络编程,90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口,即Windows Sockets规范,它不是一种网络协议,而是一套开放的、支持多种协议的Windows下的网络编程接口。现在的Winsock已经基本上实现了与协议无关,你可以使用Winsock来调用多种协议的功能,但较常使用的是TCP/IP协议。Socket实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。 微软为VC定义了Winsock类如CAsyncSocket类和派生于CAsyncSocket 的CSocket类,它们简单易用,读者朋友当然可以使用这些类来实现自己的网络程序,但是为了更好的了解Winsock API编程技术,我们这里探讨怎样使用底层的API函数实现简单的 Winsock 网络应用程式设计,分别说明如何在Server端和Client端操作Socket,实现基于TCP/IP的数据传送,最后给出相关的源代码。 在VC中进行WINSOCK的API编程开发的时候,需要在项目中使用下面三个文件,否则会出现编译错误。 1WINSOCK.H: 这是WINSOCK API的头文件,需要包含在项目中。 2WSOCK32.LIB: WINSOCK API连接库文件。在使用中,一定要把它作为项目的非缺省的连接库包含到项目文件中去。 3WINSOCK.DLL: WINSOCK的动态连接库,位于WINDOWS的安装目录下。 一、服务器端操作 socket(套接字) 1)在初始化阶段调用WSAStartup() 此函数在应用程序中初始化Windows Sockets DLL ,只有此函数调用成功后,应用程序才可以再调用其他Windows Sockets DLL中的API函数。在程式中调用该函数的形式如下:WSAStartup(WORD)(18|1),(LPWSADATA)&WSAData),其中(18|1)表示我们用的是WinSocket1.1版本,WSAata用来存储系统传回的关于WinSocket的资料。 2)建立Socket 初始化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。 3)绑定端口 接下来要为服务器端定义的这个监听的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()函数来获知其被设定的值。 4)监听 当服务器端的Socket对象绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。listen()函数使服务器端的Socket 进入监听状态,并设定可以建立的最大连接数(目前最大值限制为 5, 最小值为1)。该函数调用成功返回0,否则返回SOCKET_ERROR。 int PASCAL FAR listen( SOCKET s, int backlog ); 参 数: s:需要建立监听的Socket; backlog:最大连接个数; 服务器端的Socket调用完listen()后,如果此时客户端调用connect()函数提出连接申请的话,Server 端必须再调用accept() 函数,这样服务器端和客户端才算正式完成通信程序的连接动作。为了知道什么时候客户端提出连接要求,从而服务器端的Socket在恰当的时候调用accept()函数完成连接的建立,我们就要使用WSAAsyncSelect()函数,让系统主动来通知我们有客户端提出连接请求了。该函数调用成功返回0,否则返回SOCKET_ERROR。 int PASCAL FAR WSAAsyncSelect( SOCKET s, HWND hWnd,unsigned int wMsg, long lEvent ); 参数: s:Socket 对象; hWnd :接收消息的窗口句柄; wMsg:传给窗口的消息; lEvent:被注册的网络事件,也即是应用程序向窗口发送消息的网路事件,该值为下列值FD_READ、FD_WRITE、FD_OOB、FD_ACCEPT、FD_CONNECT、FD_CLOSE的组合,各个值的具体含意为FD_READ:希望在套接字S收到数据时收到消息;FD_WRITE:希望在套接字S上可以发送数据时收到消息;FD_ACCEPT:希望在套接字S上收到连接请求时收到消息;FD_CONNECT:希望在套接字S上连接成功时收到消息;FD_CLOSE:希望在套接字S上连接关闭时收到消息;FD_OOB:希望在套接字S上收到带外数据时收到消息。 具体应用时,wMsg应是在应用程序中定义的消息名称,而消息结构中的lParam则为以上各种网络事件名称。所以,可以在窗口处理自定义消息函数中使用以下结构来响应Socket的不同事件: switch(lParam) case FD_READ: break; case FD_WRITE、 break; 5)服务器端接受客户端的连接请求 当Client提出连接请求时,Server 端hwnd视窗会收到Winsock Stack送来我们自定义的一个消息,这时,我们可以分析lParam,然后调用相关的函数来处理此事件。为了使服务器端接受客户端的连接请求,就要使用accept() 函数,该函数新建一Socket与客户端的Socket相通,原先监听之Socket继续进入监听状态,等待他人的连接要求。该函数调用成功返回一个新产生的Socket对象,否则返回INVALID_SOCKET。 SOCKET PASCAL FAR accept( SCOKET s, struct sockaddr FAR *addr,int FAR *addrlen ); 参数:s:Socket的识别码; addr:存放来连接的客户端的地址; addrlen:addr的长度 6)结束 socket 连接 结束服务器和客户端的通信连接是很简单的,这一过程可以由服务器或客户机的任一端启动,只要调用closesocket()就可以了,而要关闭Server端监听状态的socket,同样也是利用此函数。另外,与程序启动时调用WSAStartup()憨数相对应,程式结束前,需要调用 WSACleanup() 来通知Winsock Stack释放Socket所占用的资源。这两个函数都是调用成功返回0,否则返回SOCKET_ERROR。 int PASCAL FAR closesocket( SOCKET s ); 参 数:s:Socket 的识别码; int PASCAL FAR WSACleanup( void ); 参 数: 无 二、客户端Socket的操作 1)建立客户端的Socket 客户端应用程序首先也是调用WSAStartup() 函数来与Winsock的动态连接库建立关系,然后同样调用socket() 来建立一个TCP或UDP socket(相同协定的 sockets 才能相通,TCP 对 TCP,UDP 对 UDP)。与服务器端的socket 不同的是,客户端的socket 可以调用 bind() 函数,由自己来指定IP地址及port号码;但是也可以不调用 bind(),而由 Winsock来自动设定IP地址及port号码。 2)提出连接申请 客户端的Socket使用connect()函数来提出与服务器端的Socket建立连接的申请,函数调用成功返回0,否则返回SOCKET_ERROR。 int PASCAL FAR connect( SOCKET s, const struct sockaddr FAR *name, int namelen ); 参 数:s:Socket 的识别码; name:Socket想要连接的对方地址; namelen:name的长度 三、数据的传送 虽然基于TCP/IP连接协议(流套接字)的服务是设计客户机/服务器应用程序时的主流标准,但有些服务也是可以通过无连接协议(数据报套接字)提供的。先介绍一下TCP socket 与UDP socket 在传送数据时的特性:Stream (TCP) Socket 提供双向、可靠、有次序、不重复的资料传送。Datagram (UDP) Socket 虽然提供双向的通信,但没有可靠、有次序、不重复的保证,所以UDP传送数据可能会收到无次序、重复的资料,甚至资料在传输过程中出现遗漏。由于UDP Socket 在传送资料时,并不保证资料能完整地送达对方,所以绝大多数应用程序都是采用TCP处理Socket,以保证资料的正确性。一般情况下TCP Socket 的数据发送和接收是调用send() 及recv() 这两个函数来达成,而 UDP Socket则是用sendto() 及recvfrom() 这两个函数,这两个函数调用成功发挥发送或接收的资料的长度,否则返回SOCKET_ERROR。 int PASCAL FAR send( SOCKET s, const char FAR *buf,int len, int flags ); 参数:s:Socket 的识别码 buf:存放要传送的资料的暂存区 len buf:的长度 flags:此函数被调用的方式 对于Datagram Socket而言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。对Stream Socket 言,Blocking 模式下,若是传送系统内的储存空间不够存放这些要传送的资料,send()将会被block住,直到资料送完为止;如果该Socket被设定为 Non-Blocking 模式,那么将视目前的output buffer空间有多少,就送出多少资料,并不会被 block 住。flags 的值可设为 0 或 MSG_DONTROUTE及 MSG_OOB 的组合。 int PASCAL FAR recv( SOCKET s, char FAR *buf, int len, int flags ); 参数:s:Socket 的识别码 buf:存放接收到的资料的暂存区 len buf:的长度 flags:此函数被调用的方式 对Stream Socket 言,我们可以接收到目前input buffer内有效的资料,但其数量不超过len的大小。 四、自定义的CMySocket类的实现代码: 根据上面的知识,我自定义了一个简单的CMySocket类,下面是我定义的该类的部分实现代码: / CMySocket:CMySocket() : file:/类的构造函数 WSADATA wsaD; memset( m_LastError, 0, ERR_MAXLENGTH ); / m_LastError是类内字符串变量,初始化用来存放最后错误说明的字符串; / 初始化类内sockaddr_in结构变量,前者存放客户端地址,后者对应于服务器端地址; memset( &m_sockaddr, 0, sizeof( m_sockaddr ) ); memset( &m_rsockaddr, 0, sizeof( m_rsockaddr ) ); int result = WSAStartup(WORD)(1h_addr)-s_addr; m_sockaddr.sin_addr.s_addr = lIPAddress; else m_sockaddr.sin_addr.s_addr = inet_addr( strRemote ); m_sockaddr.sin_family = AF_INET; m_sockaddr.sin_port = htons( iPort ); if( connect( m_hSocket, (SOCKADDR*)&m_sockaddr, sizeof( m_sockaddr ) ) = SOCKET_ERROR ) set_LastError( connect() failed, WSAGetLastError() ); return ERR_WSAERROR; return ERR_SUCCESS; / int CMySocket:Bind( char* strIP, unsigned int iPort )/绑定函数; if( strlen( strIP ) = 0 | iPort = 0 ) return ERR_BADPARAM; memset( &m_sockaddr,0, sizeof( m_sockaddr ) ); m_sockaddr.sin_family = AF_INET; m_sockaddr.sin_addr.s_addr = inet_addr( strIP ); m_sockaddr.sin_port = htons( iPort ); if ( bind( m_hSocket, (SOCKADDR*)&m_sockaddr, sizeof( m_sockaddr ) ) = SOCKET_ERROR ) set_LastError( bind() failed, WSAGetLastError() ); return ERR_WSAERROR; return ERR_SUCCESS; / int CMySocket:Accept( SOCKET s )/建立连接函数,S为监听Socket对象名; int Len = sizeof( m_rsockaddr ); memset( &m_rsockaddr, 0, sizeof( m_rsockaddr ) ); if( ( m_hSocket = accept( s, (SOCKADDR*)&m_rsockaddr, &Len ) ) = INVALID_SOCKET ) set_LastError( accept() failed, WSAGetLastError() ); return ERR_WSAERROR; return ERR_SUCCESS; / int CMySocket:asyncSelect( HWND hWnd, unsigned int wMsg, long lEvent ) file:/事件选择函数; if( !IsWindow( hWnd ) | wMsg = 0 | lEvent = 0 ) return ERR_BADPARAM; if( WSAAsyncSelect( m_hSocket, hWnd, wMsg, lEvent ) = SOCKET_ERROR ) set_LastError( WSAAsyncSelect() failed, WSAGetLastError() ); return ERR_WSAERROR; return ERR_SUCCESS; / int CMySocket:Listen( int iQueuedConnections )/监听函数; if( iQueuedConnections = 0 ) return ERR_BADPARAM; if( listen( m_hSocket, iQueuedConnections ) = SOCKET_ERROR ) set_LastError( listen() failed, WSAGetLastError() ); return ERR_WSAERROR; return ERR_SUCCESS; / int CMySocket:Send( char* strData, int iLen )/数据发送函数; if( strData = NULL | iLen = 0 ) return ERR_BADPARAM; if( send( m_hSocket, strData, iLen, 0 ) = SOCKET_ERROR ) set_LastError( send() failed, WSAGetLastError() ); return ERR_WSAERROR
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024-2025学年度广东省佛山市南海区高一第二学期期中提升学业水平测试历史试题(含答案)
- 二十四节气小寒课件2
- 杭州市2023反射疗法师大赛复习题复习试题
- 汽车发动机装配与检测课件:活塞的结构
- 跨领域设计服务协议书(2篇)
- 毕业综合实践报告会计
- 2025年即时配送行业成本优化策略报告:配送路径优化与效率提升研究
- 发泡轮生产扩建项目环境影响报告表
- 2025年互联网直播行业发展趋势研究报告:直播经济与产业发展
- 2025年互联网医疗平台在线问诊平台与慢性病管理服务融合报告
- 内经学研究知到章节答案智慧树2023年浙江中医药大学
- 现场急救知到章节答案智慧树2023年福建警察学院
- 电子汽车衡作业指导书
- 胡适课件完整版
- 2008年北京高考语文试题及答案
- 心脏移植手术
- 2022年北京市朝阳区幼儿园教师招聘笔试《幼儿保教知识与能力》试题及答案解析
- 计划保养手册-mrc卡设备ManitowocQ和型号所有制冰机
- 上海高一数学教材电子版
- 数字通信系统课件
- 高中物理情境化选择题专题练习
评论
0/150
提交评论