




已阅读5页,还剩13页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第 18页 Winsock基本知识 目 录1.关于网络通信21.1客户/服务器模型(c/s模型)21.2.客户和服务器通过计算机网进行连接22.winsock到底是什么?33.网络编程最基本的概念:套接口(Socket)43.1 Socket概念43.2 socket的分类43.3 用socket实现两台计算机的通信53.3.1 Winsock的启动和终止63.3.2 建立通信连接63.3.3 发送和接收数据83.3.4套接字的关闭94.本地计算机网络编程的基本函数104.1IP地址的结构104.2 地址格式转换104.3 获取本机IP地址115.Winsock的异步模式116编程举例127.参考资料17 Winsock基本知识 1. 关于网络通信Winsock是网络编程的基础,网络编程就是在计算机之间进行通信,要很好的理解网络编程我们就要从整体上把握先说说网络通信的c/s模型以及它在整个广域网上是如何实现的。1.1客户/服务器模型(c/s模型)网络应用系统通常是一个客户/服务器模型,要进行网络通信,首先我们要理解什么是c/s模型。c/s模型由两部分构成:客户端和服务器端。服务器工作的大致过程是:建立一个服务器,开启服务器使服务器处于监听状态,它检查是否有客户请求它的服务;如果有客户进行请求且条件合格则接受此客户的服务请求,即建立与客户端的连接,此后双方便可以传送数据。并且服务器能同时对多个客户端提供服务。客户端工作的大致过程:客户端向服务器提出服务请求,请求连接到服务器,如果服务器接受了它的请求,则双方可以通信。一般情况下,由客户主动发起连接请求,而发起结束通信请求方则不一定。我们可以举一个简单的例子:客户与服务器的关系类似于客户和餐厅的关系。构建餐厅的房屋、招聘服务员等可以看成建立服务器,餐厅开业相当于服务器处于监听状态,等待客户的来临。客户要想进餐厅就餐,相当于客户端发起服务请求,若餐厅答应为其服务,双方就建立了连接,可以开始服务。当然一个餐厅能接受多个客户。1.2.客户和服务器通过计算机网进行连接实际上,客户和服务器都是某台主机上的应用进程。运行客户进程的主机和运行服务器进程的主机分别位于不同的局域网中,这两个局域网通过路由器连接到广域网中。图1 客户和服务器主机通过广域网连接从上面的图中我们可以看到网络通信的大致过程,那么我们如何识别要找的主机,如何识别用到的进程呢?我们如何实现这些,就要看下面的winsock了,特别是套接口这一重要的概念。2. winsock到底是什么?也许你经常听到winsock这个词,那么winsock到底是什么呢?为了通信,网络也有自己的“语言,Internet的语言就是TCP/IP协议。Internet是在UNIX系统上发展起来的,UNIX上一个通用的成熟的编程接口是Sockets接口。而Winsock(Windows Socket)是类似于UNIX下的Sockets,为windows系统开发的一套标准的、通用的TCP/IP编程接口。目前,Windows下的Internet软件都是在Winsock的基础上开发的。在Windows98推出以前,Winsock已经集成到windows系统中,同时包括了16位与32位的编程接口。Winsock通过c语言的动态链接库方式提供给用户和软件开发者,主要有Winsock.h头文件和动态链接库winsock.dll组成。Winsock主要经历了两个版本:Winsock1.1和Winsock2.0。Winsock2.0是Winsock1.1的扩展,它向下兼容。如果你从来没有接触过网络编程,也许从UNIX下的Sockets套接口入手更简单、直观一些,更有助于你理解网络编程。但是Winsock本身也是网络编程中很基础的部分,两个环境下的基本原理是相同的,而且程序移植很方便。由于我们的开发是在windows下进行的,所以我们在这里直接介绍Winsock。3. 网络编程最基本的概念:套接口(Socket)3.1 Socket概念无论是在UNIX环境下还是在windows环境下,Socket概念都是基础。既使你知道Socket这个词,既使你常听到人们谈到“Socket”,而你却不知道其确切含义,它是干什么用的呢?Socket在英文中的意思是插座,通常我们称socket为套接口。套接口(Socket)是通信的基础,一个套接口是通讯的一端。在这一端上你可以找到与其对应的一个名字。一个正在被使用的套接口都有它的类型和与其相关的进程。在UNIX里,所有的东西都是文件,你的CDROM是文件,你的显示器是文件,你的硬盘也是文件,所以,你想和网络上其他程序通信的时候就要通过文件描述符。既然如此,现在你或许会想:我该怎么样得到网络通讯的文件描述符呢?你就要用到系统调用socket(),他返回套接口文件描述符,然后你可以把这个文件描述符当作普通的文件来操作。实际中,我们用IP地址唯一的标识一个主机,然后根据指定的端口号找到运行在主机上的客户或服务器进程,这样我们就找到了某个特定主机上的特定进程。一个TCP连接的套接口对是一个定义该连接的两个端点的四元组:本地IP地址,本地TCP端口号,远程IP地址,远程TCP端口号。套接口对唯一标识一个互联网上的TCP连接。标识每个端点的两个值就称为一个套接口。我们了解了客户/服务器模型以及如何识别客户和服务器进程,那么具体怎样用socket实现两台计算机的连接和通信呢?3.2 socket的分类套接口可以根据通讯性质分类;这种性质对于用户是可见的。应用程序一般仅在同一类的套接口间通讯。不过只要底层的通讯协议允许,不同类型的套接口间也照样可以通讯。用户目前可以使用两种套接口,即流套接口(SOCK_STREAM)和数据报套接口(SOCK_DGRAM)。流套接口提供了双向的,有序的,无重复并且无记录边界的数据流服务。数据报套接口支持双向的数据流,但并不保证是可靠,有序,无重复的。也就是说,一个从数据报套接口接收信息的进程有可能发现信息重复了,或者和发出时的顺序不同。数据报套接口的一个重要特点是它保留了记录边界。3.3 用socket实现两台计算机的通信从上面的介绍我们知道服务器和客户各有一个套接口,二者组成一个套接口对,形成一个连接进行通行,怎样建立套接口以及怎样进行通信,整个过程如下图所示: 图 2 面向连接的流式套接字编程流程示意图图中的流程非常清楚,我们不再将整个流程进行文字描述,而是详细的介绍一下这些函数,它们都包含在头文件winsock.h中。3.3.1 Winsock的启动和终止应用程序在使用Windows Sockets DLL之前必须先调用函数WSAStartup()。上面的流程中我们并没有列出该函数,事实上由于winsock由DLL形式提供,为了完成一系列的初始化操作,每一个使用winsock的应用程序都必须进行WSAStartup()函数调用,并且只有在成功的完成调用之后才能使用scoket。u WSAStartup()函数函数的原形如下:int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);wVersionRequired表示欲使用的winsock API的版本,这是一个WORD类型的整数,它的高位字节是次版本号,低位字节是主版本号;lpWSAData是指向WSADATA结构的指针,用于返回Windows Sockets DLL的一些技术细节。如果初始化成功则函数返回0,否则返回各种错误代码。u WSACleanup():结束 Windows Sockets DLL 的使用 格式: int PASCAL FAR WSACleanup( void ); 参数: 无 返回值:成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 每个WSAStartup()函数必须和一个WSACleanup()函数相对应。当应用程序终止时,必须调用WSACleanup()将自己从DLL中注销,并释放相应的资源。3.3.2 建立通信连接u socket()函数:创建套接字任何用户要进行通信都要调用socket()函数指定通信协议的类型,创建套接字。函数的原形:int socket(int family,int type,int protocol);参数参数family指明协议族,也就是利用它来分辨地址的类型,一般为AF_INET表示在Internet上的socket;type指明套接口类型,也即是通信的类型可以为SOCK_STREAM或SOCK_DGRAM;protocol参数说明该套接字使用的协议族中的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。若函数调用成功,则返回一个套接口描述字,简称套接字(sockfd);若调用失败,则返回INVALID_SOCKET。u bind()函数:指定本地地址一个套接字用socket()创建后,它其实还没有与任何特定的本地或目的地址相关联。在很多情况下,应用程序并不关心他们使用的本地地址,这时可以不调用此函数,而由协议软件为他们选择一个。如果要使用指定的端口,则创建了一个套接口之后,服务器必须调用bind()函数给套接口分配一个本地协议地址,捆绑端口。函数原形:int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);参数sockfd是绑定的套接字描述符,是由socket返回的;myaddr是与套接字绑定的一个本地地址结构,其长度可变,结构随协议族的不同而不同;addrlen是myaddr的长度。返回0表示函数调用成功,返回-1(SOCKET_ERROR)表示出错。u connect()函数:将套接字连接到目的地址初始创建的套接字并未与任何外地目的地址关联,客户端调用connect()为套接字绑定一个永久的目的地址,将它置于已经连接的状态。对数据流方式的套接字,必须在传输数据前,调用connect()构造一个与目的地的TCP连接,并不能构造连接时返回一个差错代码。如果是数据报方式则不是必须在传输数据之前调用connect。函数原形:int connect(int s,const struct sockaddr *servaddr,socklen_t addrlen);s是本地套接字描述符;servaddr是指向对方套接字地址结构的指针,这里的套接口地址是服务器的套接口地址,包括服务器的IP地址和端口号,指明了要连接到的服务器;addrlen是对方套接字地址结构的长度。返回0表示调用成功,返回-1表示出错。u listen()函数:设置等待连接状态对于一个服务器的程序,当申请到套接字,并调用bind()与本地地址绑定后,就应该等待某个客户机的请求连接。函数listen()就是把套接字置为这种状态,它仅被服务器调用,它使服务器的套接口成为一个监听套接口。事实上当用socket()函数建立一个套接口时,它是一个主动套接口,也就是说它应该调用connect()函数向服务器发起连接的套接口,函数Listen()将此套接口转变为被动套接口,使它接受客户向它发出的连接请求。函数原形:int listen(int sockfd,int backlog); 参数sockfd是套接字描述符;backlog是指明等待连接的队列的最大长度,可以取1-5。返回0表示调用成功,返回-1表示出错。u accept()函数:接收连接请求服务器进程使用系统调用socket,bind和listen创建一个套接字,将它绑定到知名的端口,并指定连接请求的队列长度,进入监听状态,当有连接请求到达时,服务器调用accept()接收连接请求,它返回一个新建立的连接。函数原形:int accept(int sockfd,struct sockaddr * cliaddr,socklen_t *addrlen);参数sockfd是套接字描述符;指针cliaddr用于返回请求连接的客户方套接字地址;指针addrlen用于返回该地址结构的长度。如果没有发生错误,则返回新的套接字,否则返回INVALID_SOCKET。值得注意的一点是,当accept()执行成功,它的返回值是内核自动生成的一个全新的描述字,它与客户进行数据通信,我们称之为会话套接口。accept()参数中的scokfd是监听套接口,accept()返回的套接口是一个已经连接到某个客户套接字的已连接套接口(会话套接口)。我们一定要区分这两种套接口。一个服务器只生成一个监听套接口且一直存在,直到服务器关闭。内核则是为每个被接受的客户创建一个已连接套接口,服务器完成客户的服务时,关闭与之通信的已连接套接口。我们可以看下面的图示来更好的区分这两种套接字。 图 3 accept()函数接收请求,建立新的套接字从图中我们能够很清楚的看到,与客户进行通信的套接口并不是listenfd,而是新建立的connfd套接口。listenfd套接口继续监听,检查是否有新的连接请求,如果有新的客户请求连接,则再通过accept调用建立一个新的套接口。3.3.3 发送和接收数据当服务器端和客户端建立连接以后,就可以在两台机器之间传送数据,也即是用winsock API函数在两台连接成功的机器之间进行通信。下面我们介绍几个传送数据的函数,无论是客户端,还是服务器端都可以使用这些函数:在数据流方式中,一个连接建立以后,或者在数据报方式下,调用了connect()进行了套接字与目的地址的绑定后,就可以调用send()和recv()进行数据传输。u send():使用连接好的 Socket 发送数据 格式: int send( SOCKET s, const char FAR *buf, int len, int flags );参数 s是Socket 的识别码;buf指向发送缓冲区的首址;len是缓冲区的长度; flags指定传输控制的方式,一般设为0。 传回值: 成功 - 送出的数据的长度 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 此函数适用于连接式的 Datagram 或 Stream Socket 来传送资料。 对 Datagram Socket 而言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。u recv():自 Socket 接收数据 格式: int recv( SOCKET s, char FAR *buf, int len, int flags );参数s是Socket 的识别码;指针buf指向接收缓冲区的首址;len是buf 的长度 ;flags指定传输控制的方式,一般设为0。 传回值: 成功 - 接收到的数据长度 (若对方 Socket 已关闭,则为 0) 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 此函数适用于连接式的 Datagram Socket 或 Stream Socket。对 Stream Socket而言,我们可以接收到目前有效的 数据,但其数量不超过 len 的大小。对 Datagram Socket 言,只取出第一个 datagram;若是该 datagram 大于使用者提供的储存空间,那么只有该空间大小的资料被取出,多余的资料将丢失,且回复错误信息。如果我们以数据报的方式通信,由于事先不用建立连接,所以可以跳过connect()而直接用recvfrom()和sendto()两个函数进行通信:u recvfrom():读取一个 Datagram,并储存数据来源的地址。格式: int recvfrom( SOCKET s,char FAR *buf,int len,int flags, struct socketaddr FAR *from,int FAR*fromlen );参数s,buf,len,flags与send()中的相同;指针from返回数据发送者的地址;fromlen是from 的大小。传回值: 成功 - 接收到的数据长度 (若对方 Socket 已关闭,则为 0) 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 对 Stream Socket而言,其作用与 recv() 相同,参数 from 及 fromlen 将不被用到。u sendto():将数据送到指定的目的地。 格式: int sendto( SOCKET s,const char FAR *buf,int len,int flags,const struct sockaddr FAR *to,int tolen ); 参数s,buf,len,flags与send()中的相同;指针to指向数据发送的目的地址;tolen是to的大小。传回值: 成功 - 送出的资料长度 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 此函数适用于 Datagram 或 Stream Socket 来传送数据到指定的位址。对Datagram Socket 言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。3.3.4套接字的关闭当要关闭通讯连结的时候,任何一方都可以调用int shutdown(SOCKET s,int how);来关闭套接字的指定功能。再调用int closeSocket(SOCKET s);来关闭套接字句柄。这样一个通讯过程就算完成了。 u shutdown():停止 Socket 接收/传送的功能 格式: int PASCAL FAR shutdown( SOCKET s, int how ); 参数: s是Socket 的识别码,how代表该停止那些动作的标识。若 how 的值为 0,则不再接收数据。 若 how 的值为 1,则不再允许传送数据。 若 how 的值为 2,则不再接收且不再传送数据。 传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError()可得知原因) shutdown() 函数并没有将 Socket 关闭,所以该 Socket 所占用之资源必须在呼叫closesocket() 之后才会释放。u closesocket():关闭套接字当某个套接字的通信结束时,必须调用该函数关闭指定的套接字。 格式: int PASCAL FAR closesocket( SOCKET s ); 参数: s是Socket 的识别码 传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 3.4 Winsock错误处理Winsock使用WSAGetLastError()函数来获得最近操作的错误代码。WinSock API函数调用后大多要返回一个值说明本次调用是否成功。如果不成功则可以调用WSAGetLastError()得到错误代码。需要注意的一点是,如果你作网络编程就一定要检查任何一个WinSock API函数的调用结果,因为很多时候函数调用并不一定成功。上面介绍的函数,返回值类型是int的话,如果函数调用失败的话,返回的大多是SOCKET_ERROR。4. 本地计算机网络编程的基本函数4.1 IP地址的结构IP地址是网络中的一个重要概念,网络编程更是频繁的用到IP地址,上面我们介绍函数的时候有很多地址结构指针,我们一定要了解IP地址的结构:struct sockaddr_inshort sin_family ;u_short sin_prot ;struct in_addr sin_addr ;char sin_sero8 ; 这个结构包含了我们需要建立连接的本地的地址,包括地址族、IP和端口信息。sin_family字段我们必须把它设为AF_INET,这是告诉WinSock使用的是IP地址族。sin_prot就是我们要用来通讯的端口号。sin_addr就是我们要用来通讯的IP地址信息。4.2 地址格式转换我们设置IP地址和port端口时,就必须把主机字节转化成网络字节后才能使用。u htons():将u_short的值由主机字节转换成网络字节 格式:u_short PASCAL FAR htons( u_short hostshort ); 参数: hostshort一个主机字节方式的数 函数返回一个网络字节方式的址。 u inet_addr():将字串格式的地址转换成 32 位 unsigned long 格式 格式: unsigned long PASCAL FAR inet_addr( const char FAR *cp ); 参数: cp是代表地址的点格式(dotted) 字串 返回值: 成功 - 一个表示 Internet 位址的 unsigned long 失败 - INADDR_NONE 此函式将一点格式的位址字串转换成适用之Intenet位址。 点格式字串可为以下四种方式之任一: (i) a.b.c.d (ii) a.b.c (iii) a.b (iv) au inet_ntoa():将一网路位址转换成点格式字串。 格式: char FAR * PASCAL FAR inet_ntoa( struct in_addr in ); 参数: in代表 Internet 地址的结构 返回值: 成功 - 表示地址的点格式字串 失败 - NULL 此函式将一 Internet 位址转换成a.b.c.d字串格式。4.3 获取本机IP地址u gethostname():获取目前使用者使用的主机的名称 格式: int PASCAL FAR gethostname( char FAR *name, int namelen ); 参数: name用来存放 获取的主机名称;namelen是name 的大小。 返回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) u gethostbyname():利用主机的名称来获取该主机的资料。 格式: struct hostent FAR * PASCAL FAR gethostbyname( const char FAR *name ); 参数: name是主机名称 返回值: 成功 - 指向 struct hostent 的指针;失败 - NULL (呼叫 WSAGetLastError() 可得知原因) 此函式是利用 host 名称来获取其他的资料,如 host 的位址、别名,位址的型态、长度等。Hostent 结构如下:struct hostent char FAR *h_name; char FAR * FAR *h_aliases; short h_addrtype; short h_length; char FAR * FAR *h_addr_list; 5. Winsock的异步模式为了实现非阻塞通信,Winsock实现了异步模式。u Select()函数函数原形:int select( int nfds , fd_set FAR* readfds , fd_set FAR* writefds,fd_set FAR* exceptfds,const struct timeval FAR * timeout ) ; 函数用来检查你要调用的Socket套接字是否已经有了需要处理的数据。select包含三个Socket队列,分别代表:readfds ,检查可读性,writefds,检查可写性,exceptfds,例外数据。timeout是select函数的返回时间。 例如,我们想要检查一个套接字是否有数据需要接收,我们可以把套接字句柄加入可读性检查队列中,然后调用select,如果,该套接字没有数据需要接 收,select函数会把该套接字从可读性检查队列中删除掉,所以我们只要检查该套接字句柄是否还存在于可读性队列中,就可以知道到底有没有数据需要接收了。WinSock提供了一些宏用来操作套接字队列fd_set。FD_CLR( s,*set) 从队列set删除句柄s。FD_ISSET( s, *set) 检查句柄s是否存在与队列set中。FD_SET( s,*set )把句柄s添加到队列set中。FD_ZERO( *set ) 把set队列初始化成空队列。u WSAAsyncSelect()WSAAsyncSelect(异步选择)模型:WSAASyncSelect模型就是把一个窗口和套接字句柄建立起连接,套接字的网络事件发生时时候,就会把某个消息发送到窗口,然后可以在窗口的消息响应函数中处理数据的接收和发送。int WSAAsyncSelect( SOCKET s, HWND hWnd , unsigned int wMsg , long lEvent ) ;这个函数可以把套接字句柄和窗口建立起连接,wMsg 是我们必须自定义的一个消息。lEvent就是制定的网络事件。包括FD_READ , FD_WRITE , FD_ACCEPT,FD_CONNECT,FD_CLOSE 。几个事件。例如,我需要接收FD_READ , FD_WRITE , FD_CLOSE 的网络事件。可以调用WSAAsyncSelect( s , hWnd , WM_SOCKET , FD_READ | FD_WRITE | FD_CLOSE ) ;6编程举例上面我们说了这么多,你也许会被这些连来连去的函数搞的“头晕”,或许你还是无法理解什么是套接口以及怎样进行通信,好吧,让我们从一个简单的程序串联一下这些内容。建立两个控制台应用程序,一个服务器,一个客户端。在程序的头文件中要包括winsock.h,在Projectsettings中的link控制板上,在Object/library modules编辑框中添加Winsock的库文件Wsock32.lib。在服务器端我们解析出本机的IP地址显示给用户,然后让用户指定端口。服务器端源程序:#include #include #include void main()SOCKET sersock,consock;/定义监听接口和会话接口 WSADATA wsaData;struct sockaddr_in seraddr,cliaddr; /定义服务器和客户地址变量char hostname255; /主机名 char * hostip; /主机ip PHOSTENT hostinfo; /定义一个主机信息结构变量unsigned short serport; /服务端口int result,len,recvnum;char recvbuff50; /接收缓冲区fd_set readfds; /if (WSAStartup(0x101,&wsaData) printf(WSAStartup() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码exit(0);else /初始化成功printf(WSAStartup() sucessfully!n);sersock=socket(AF_INET,SOCK_STREAM,0); /建立套接口if(sersock=INVALID_SOCKET) /出错printf(socket() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码exit(0);elseprintf(socket() sucessfully!n);/获取本机IP地址 if( gethostname ( hostname, sizeof(hostname) != 0) /返回标准的本机主机名发生错误 printf(gethostname() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码exit(0);elseprintf(gethostname() sucessfully!n); if(hostinfo = gethostbyname(hostname) != NULL) /根据主机名返回主机信息hostip = inet_ntoa (*(struct in_.addr *)*hostinfo-h_addr_list); printf(The host IP is:%sn,hostip); /输出本机的Ip地址else/gethostbyname失败printf(gethostbyname() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码 exit(0); printf(please input a port(better bigger than 1024):);scanf(%d,&serport);seraddr.sin_family=AF_INET;seraddr.sin_port=htons(serport); /端口seraddr.sin_addr.S_un.S_addr=inet_addr(hostip); /ipresult=bind(sersock,(sockaddr *)&seraddr,sizeof(seraddr); /绑定套接口 if(result!=0) /出错printf(bind() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码exit(0);elseprintf(bind() sucessfully!n);result=listen(sersock,3); /设置监听状态 if(result!=0) /出错printf(listen() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码exit(0);elseprintf(listen() sucessfully!n); printf(begin listening.n);len=sizeof(cliaddr);consock=accept(sersock,(sockaddr *)&cliaddr,&len);if (consock=SOCKET_ERROR)printf(accept() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码exit(0);else printf(accept() sucessfully!n);printf(connect from %s:%dn,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port);FD_ZERO(&readfds);/清空fdset与所有文件句柄的联系。 FD_SET(consock,&readfds);/建立文件句柄consock与fdR的联系。 select(consock+1, &readfds, NULL, NULL,NULL); if (FD_ISSET(consock, &readfds) /可以读recvnum=recv(consock,recvbuff,lstrlen(recvbuff),0);recvbuffrecvnum=0;printf(the number of char that we received is:%dn,recvnum);printf(the data we received is:%sn,recvbuff);else printf(the socket cant read!); closesocket(sersock); /关闭套接口closesocket(consock); 客户端源程序:#include #include #include void main() SOCKET clisock;/定义套接口 int ret,sendnum; WSADATA wsaData; struct sockaddr_in seraddr; /定义服务器地址 char serIp40; char * ip; /服务器ip地址 unsigned short port; /端口 char sendbuff50; /发送缓冲区 if (WSAStartup(0x101,&wsaData) printf(WSAStartup() Error!); printf(The Error is:%dn,WSAGetLastError(); /取得错误代码 e
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 混凝土配合比变动管理方案
- 水管所业务大讲堂课件
- 水稻第三期课件
- 农副产品加工设备维护与保养方案
- 水痘相关知识
- 造型基础色彩构成设计83课件
- 2025版猎聘服务专项合作协议(初创企业)
- 二零二五年度房产物业管理服务协议书
- 2025版影视公司离婚协议与版权及收益分配合同
- 2025版宾馆房间租赁合同及商务会议服务协议
- 餐饮店品牌授权使用合同范本
- 学堂在线 走进医学 章节测试答案
- 蔬菜温室大棚项目可行性研究报告书书
- 闵行区2024-2025学年下学期七年级数学期末考试试卷及答案(上海新教材沪教版)
- 八大特殊作业管理培训
- 费用报销合规培训
- 义务教育科学课程标准(2022年版)
- Q-GDW11628-2016新能源消纳能力计算导则
- 十五五文物规划思路
- 2025年修订版《雇佣合同》全文
- 公安宣传工作管理制度
评论
0/150
提交评论