收藏 分享(赏)

第2章 Winsock编程接口.ppt

上传人:hwpkd79526 文档编号:7414438 上传时间:2019-05-16 格式:PPT 页数:94 大小:1.36MB
下载 相关 举报
第2章  Winsock编程接口.ppt_第1页
第1页 / 共94页
第2章  Winsock编程接口.ppt_第2页
第2页 / 共94页
第2章  Winsock编程接口.ppt_第3页
第3页 / 共94页
第2章  Winsock编程接口.ppt_第4页
第4页 / 共94页
第2章  Winsock编程接口.ppt_第5页
第5页 / 共94页
点击查看更多>>
资源描述

1、,第二章 Winsock编程接口,Windows套接字简介 字节顺序和Winsock的寻址方式 Winsock API 基本函数 数据报套接字编程 流式套接字编程,1. Windows 套接字简介,Winsock来源,Sockets本来是Unix操作系统上流行的一种网络编程接口(API)。 API :Application Programming Interface 发展过程:1983年在Berkeley大学4.2BSD UNIX中首先使用,因此被称为Berkeley Socket API(只支持TCP/IP协议) 。后来在4.3BSD UNIX中增加了对OSI网络协议的支持。 应用平台:UN

2、IX、LINUX 产生Winsock: Winsock API在1991年根据4.3BSD UNIX的Berkeley Socket制定的。,Winsock规范,Winsock 规范:一套开放的、支持多种协议的Windows下的网络编程接口。主要支持TCP/IP协议。 Winsock 规范主要包括Windows提供的API函数: 符合Berkeley Socket风格的库函数; 针对Windows的一组扩展库函数。 发展过程:1991年的1.0版到1997年的2.2版(主要扩充了对其它协议的支持)。 应用平台:Windows系列,Winsock实现库两个版本:Winsock1和Winsock2

3、。 现在大都使用Winsock2, Winsock2库的最新版本是2.2。,Winsock实现库,采用Winsock 1的应用必须包含winsock.h 头文件。 使用Winsock 2的应用必须包含winsock2.h 头文件。,不同平台对应不同的库版本。,套接字基本概念,套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。,在编写网络应用程序时,应先申请套接字,以后两台机器上的程序通过该套接字进行通信。,在网络程序编程中,通过将IP、端口与一个套接字绑定,并指明通信协议,从而来实现应用程序与TCPIP协议的交互。,套接字通信模型,客户端,服务器,基于TCP/IP 的网络,

4、中间环节,套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。如下图:,套接字中的信息通过驱动程序送入网卡,然后经网络发送到远端服务器,网卡将接收到的信息通过驱动程序送入套接字,进程C,进程S,套接字(Socket)分类,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW),打电话,在TCP/IP协议组中,使用TCP协议来实现流式套接字。,发信,在TCP/IP协议组中,使用UDP协议来实现数据报套接字。,该套接字允许对底层协议(如IP或ICMP)进行直接访问,常用来测试新安装的网络设备,以及对流经网卡的数据进行捕获分析。,

5、它定义了一种无连接、不可靠的双向数据传输服务。,它定义了一种可靠的、面向连接的双向数据传输服务。,2. 字节顺序和Winsock的寻址方式,字节顺序 含义:占内存多于一个字节类型的数据在内存中的存储顺序。通常有如下两种存储顺序: 1 Little endian:将低序字节存储在起始地址(低序优先) 2 Big endian:将高序字节存储在起始地址(高序优先),内存地址 1000 1001 1002 1003,低序优先存储顺序:0x78 0x56 0x34 0x12,高序优先存储顺序:0x12 0x34 0x56 0x78,然而处于主机上的数据却因不同的CPU上运行的操作系统的不同,字节顺序也

6、不同,参见下表。,通常根据所处的位置不同,低序优先字节顺序和高序优先字节顺序我们又分别称为主机字节顺序和网络字节顺序。,处理器 操作系统 字节排序 HP-PA NT 低序优先 HP-PA UNIX 高序优先 Intelx86 全部 低序优先 Motorola680x() 全部 高序优先,因此,我们常说的主机字节顺序,就是低序优先,但主机上的字节顺序却不尽都是低序优先。,网络字节顺序是TCP/IP中规定的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。,不同字节顺序转换函数 主机字节顺序 hhost;网络字节顺序 nnetwork u_

7、short htons ( u_short hostshort ); 把一个u_short 型的主机字节顺序存储的数转换为网络字节顺序存储字节数转换 u_long htonl ( u_long hostlong ); 把一个u_long型的主机字节顺序存储的数转换为网络字节顺序存储 字节数转换 u_short ntohs ( u_short netshort ); 把一个u_short 型的网络字节顺序存储的数转换为主机字节顺序存储字节数转换 u_long ntohl ( u_long netlong ); 把一个u_long型的网络字节顺序存储的数转换为主机字节顺序存储字节数转换,Winso

8、ck 寻址 Winsock要兼容多个协议,所以必须使用通用的寻址方式。 TCP/IP(IP地址,端口)来指定一个地址,其它协议不一定如此。 sockaddr结构,struct sockaddr u_short sa_family; /2个字节 共16位char sa_data14; /14个字节 ; /共16个字节,sa_family:AF_UNIX Unix internal protocols AF_INET Internet protocols常用 本课程使用AF_NS Xerox NS protocolsAF_IMPLINK IMP link layer 其中,AF_ 代表“addre

9、ss family” sa_data 在不同的地址家族中存放的数据不同。,sockaddr_in结构 (Winsock定义的sockaddr结构的TCP/IP版本)本质和sockaddr是相同的结构(大小一致)sockaddr_in更容易操作。,struct sockaddr_in short sin_family; / / Address family 2字节u_short sin_port; / / 16-bit port number 2字节struct in_addr sin_addr; / / 32-bit (IP)地址4字节char sin_zero 8; / / unused 8

10、字节 ; /共16个字节 该结构与sockaddr兼容,供用户填入参数,sockaddr_in结构 成员说明。,sin_family:必须设置为AF_INET,它告诉Winsock程序使用的是IP地址家族,sin_port:指定TCP或UDP通信服务的端口。0-1023:公共服务使用。 如80为HTTP服务的端口1024- 65535 :可以由普通用户使用。,struct in_addr sin_addr :IP地址。,sin_zero:为了和sockaddr保持一致。,in_addr结构 在in_addr中采用共用体类型。,struct in_addr union /共用体struct u_

11、char s_b1,s_b2,s_b3,s_b4; S_un_b;/ 1+1+1+1=4字节struct u_short s_w1,s_w2; S_un_w;/ 2+2=4字节 u_long S_addr; /4字节 S_un; struct in_addr sin_addr;/sockaddr_in结构中的IP地址,共用体:几个不同的变量共占一段内存的结构称为“共用体”。共用体变量所占的内存长度等于最长的成员的长度。这里共用体的三个变量长度一致。,点分 十进制记法,11000000 10101000 00000001 00001100,192 . 168 . 1 . 12,0xC0,0xA8

12、,0x01,0x0C,IP地址设置,对地址进行设置:注意要把多字节数转换成网络字节顺序假设有IP地址 “192.168.1.12” 4字节数据十进制表示 对于struct in_addr sin_addr可以有如下赋值方法:第一种方法(每个数都是单字节,不用转换)sin_addr.S_un.S_un_b.s_b1=192;sin_addr.S_un.S_un_b.s_b2=168;sin_addr.S_un.S_un_b.s_b3=1;sin_addr.S_un.S_un_b.s_b4=12;,第二种方法(转换成网络字节顺序 即高位在前)192 168 1 12 对应的16进制 0xC0 0x

13、A8 0x01 0x0C192 168 2字节16进制 0xC0A8 1 12 2字节16进制 0x010Csin_addr.S_un.S_un_w.s_w1=htons(12*16*16*16+10*16+8);sin_addr.S_un.S_un_w.s_w2=htons(1*16*16+12);,第三种方法 (转换成网络字节顺序 即高位在前)192.168.1.12 4字节16进制 0xC0A8010Csin_addr.S_un.S_addr=htonl(12*pow(16,7)+10*pow(16,5) +8*pow(16,4)+1*pow(16,2)+12);,IP地址转换函数(点分

14、十进制IP地址 网络字节顺序IP地址),char * inet_ntoa ( struct in_addr in ); 把一个 (Ipv4)32位网络字节顺序IP地址转换成”aa.bb.cc.dd”格式的字符串 unsigned long inet_addr ( const char * cp ); 把一个 ”aa.bb.cc.dd”格式的IP地址字符串转换为(Ipv4)32位网络字节顺序IP,因此可以有更简便的方法,也是最常用的方法sin_addr.S_un.S_addr=inet_addr(“192.168.1.12“);,struct sockaddr_in short sin_fami

15、ly; / / Address family 2字节u_short sin_port; / / 16-bit port number 2字节struct in_addr sin_addr; / / 32-bit (IP)地址4字节char sin_zero 8; / / unused 8字节 ; /共16个字节,下面初始化一个sockaddr_in结构,sockaddr_in addrSrv; addrSrv.sin_family=AF_INET; /把16位主机字节转换为网络字节 addrSrv.sin_port=htons(6789); /把点分制转换为32位网络字节 addrSrv.si

16、n_addr.S_un.S_addr=inet_addr(“127.0.0.1“);,总 结,套接字的基本概念 套接字的通信模型 Winsock的寻址方式 主机字节顺序(低位在前) 网络字节顺序(高位在前) 两种顺序间的转换 IP地址设置,3. Winsock API基本函数,Winsock API环境准备 #include /包含了绝大部分socket函数和相关结构类型的声明 #pragma comment(lib, “WS2_32“) /链接到WS2_32.lib,打开WinsockWSAStartup() 加载可用的Winsock 实现库 函数形式 int WSAStartup ( WO

17、RD wVersionRequested, /传入参数 LPWSADATA lpWSAData /传出参数 ); /typedef unsigned short WORD;/2个字节 16位 功能说明:检查系统中是否有可用的Winsock 实现库,并加载该实现库。网络应用程序开始必须调用此函数。,参数说明:,WORD wVersionRequested 含义:用来指定想要加载的Winsock库的版本。表示一个字(2个字节)。高位字节指定副版本,低位字节制定主版本。目前的Win32平台而言,Winsock2库的最新版本是2.2(Win95为Winsock1.1),参数设定: 假设加载Winsoc

18、k2.2版 。 指定此参数的值为0x0202; wVersionRequested= 0x0202或使用宏MAKEWORD(x, y): 通过宏MAKEWORD来指定参数的值 。x是高位字节,y是低位字节 MAKEWORD(2, 2)指定版本为Winsock2.2版,typedef struct WSAData WORD wVersion;/调用者希望使用的版本号WORD wHighVersion;/库文件支持的最高版本char szDescriptionWSADESCRIPTION_LEN+1; /Winsock库描述字符串 如 Winsock2.0库char szSystemStatusW

19、SASYS_STATUS_LEN+1; /系统状态字符串 如:Runningunsigned short iMaxSockets; / Winsock2库已废弃参数unsigned short iMaxUdpDg;/ Winsock2库已废弃参数char * lpVendorInfo; / Winsock2库已废弃参数 WSADATA, * LPWSADATA;,LPWSADATA lpWSAData 一个指向WSADATA结构的指针,用来返回加载库的详细信息。,WSADATA * lpWSAData ; 等价于 LPWSADATA lpWSAData ;,返回0则正确,否则返回错误。错误代码

20、可以通过WSAGetLastError()来获取。下面只举几个例子说明。更多信息可以MSDN获取,也可到winsock.h或 winsock2.h中查找。如:WSASYSNOTREADY:10091 加载的Winsock 库不存在 WSAEFAULT:10014 lpWSAData参数是无效的指针,返回值:,终止使用WinsockWSACleanup() 函数形式:int WSACleanup ( ); 功能说明:该函数终止应用程序对Winsock 库的使用,释放加载的Winsock库。每一个WSAStartup的调用必须对应一个WSACleanup的调用。 返回值:调用成功返回0;否则SOC

21、KET_ERROR被返回, 具体错误可以通过函数 WSAGetLastError()来获取。 SOCKET_ERROR是系统宏定义值为-1。,#include / 标准输入输出系统文件 #include / winsock声明文件 #pragma comment(lib, “WS2_32“) / 链接到WS2_32.lib void main()/通过载入Winsock库,来使用Winsock的相关函数WSADATA wsaData; /用来返回Winsock库的详细信息 WORD version = MAKEWORD(2, 2); / wVersionRequested=0x0202; in

22、t ret = WSAStartup(version, ,加载释放举例:,WSADATA,/*进行版本号匹配的检查 */if (LOBYTE( wsaData.wVersion ) != 2| /取低位字节 主版本HIBYTE( wsaData.wVersion ) != 2) /取高位字节 幅版本printf(“ Winsock库版本不匹配n “);WSACleanup( ); /释放库return; printf(“wVersion=%dn”,wsaData.wVersion);/希望使用版本printf(“wHighVersion=%dn”,wsaData.wHighVersion);/

23、最高版本printf(“szDescription=%sn”,wsaData.szDescription);/库描述printf(“szSystemStatus=%sn”,wsaData.szSystemStatus);/系统状态WSACleanup( );/释放库 ,wVersion=514 wHighVersion=514 szDescription=WinSock 2.0 szSystemStatus=Running,514说明版本号是2.2 0x0202 :十进制 21616+2=514 WinSock 2.0指 WinSock 2库,WSADATA,创建套接字socket(),函数形

24、式 : SOCKET socket ( int af, /说明套接字使用的协议地址族 int type, /描述套接字的协议类型 int protocol /说明套接字使用的特定协议字段 );,为应用程序创建套接字,返回值SOCKET : 系统提供的类型定义 typedef u_int SOCKET; 调用成功:返回新创建的套接字描述符(一个编号) 。 调用失败:返回INVALID_SOCKET(系统宏定义值0)。 可以调用WSAGetLastError()来获取具体错误的代码。 创建套接字后系统会为其分配相应的系统缓冲区。,举例说明 :流式和数据报套接字中协议字段指定0时,取缺省的协议 SO

25、CKET sockSrv=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);/等同上一行 SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0); /等同上一行 SOCKET sockSrv=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);SOCKET sockSrv=socket(AF_INET,SOCK

26、_RAW,IPPROTO_IP);,关闭套接字closesocket(),函数形式 :int closesocket (SOCKET s );,关闭一个不再使用的套接字。,调用成功:返回0; 调用失败:返回SOCKET_ERROR (系统宏定义,值为-1) 具体错误代码:调用WSAGetLastError()来获取。,绑定套接字到指定的Socket地址bind(),函数形式 : int bind (SOCKET s, const struct sockaddr * name, /Socket地址int namelen /指定地址参数(name)的长度);,把一个套接字与一个Socket地址联系

27、起来。,调用成功返回0,否则将返回SOCKET_ERROR,SOCKET sListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); sockaddr_in addrSrv;/地址名字 /进行绑定 bind(监听套接字, 地址,地址长度);if (SOCKET_ERROR =bind(sListen,(SOCKADDR*),sockaddr_in addrSrv;/地址名字addrSrv.sin_family=AF_INET;/协议地址族int PORT=4000;addrSrv.sin_port=htons(PORT);addrSrv.sin_addr.

28、S_un.S_addr=inet_addr(“127.0.0.1“);,监听连接listen(),函数形式: int listen ( SOCKET s, int backlog /指定正在等待连接的最大队列长度 );,设置套接字进入监听连接请求的状态,以准备接收客户发出的连接请求。,调用成功返回0,否则将返回SOCKET_ERROR,/进入监听状态if (SOCKET_ERROR=listen(sListen,5) /5表示等待连接队列的长度printf(“监听失败:%dn“,WSAGetLastError();return;,请求连接connect(),函数形式 : int connect

29、 ( SOCKET s, const struct sockaddr* name, int namelen );,在客户端当一个套接字建立好之后,就要调用connect()函数,向服务器端提出连接请求。,调用成功返回0,否则将返回SOCKET_ERROR,使用该函数请求建立连接时,将激活建立连接的三次握手,用来建立一条与服务器的TCP连接。,/connect(客户端套接字,服务端地址,服务端地址长度);if(SOCKET_ERROR= connect(sockClient,(sockaddr*),接受连接accept(),函数形式 : SOCKET accept ( SOCKET s, str

30、uct sockaddr* addr,/存放发出连接请求的客户机的地址 int * addrlen /指出客户机套接字地址的长度 );,服务器端调用accept()函数来接受来自客户端的连接请求。,调用失败:返回INVALID_SOCKET ; 调用成功:返回一个新建套接字 。新建套接字 客户机套接字 原来的监听套接字,仍然处于监听连接状态。,该函数只适用于TCP服务器。缺省是阻塞函数,若队列中无连接请求,则阻塞等待,直到有连接请求,才继续执行。,SOCKET SockConn;/声明和客户端连接的套接字SOCKADDR_IN addrClient;/来自客户端的地址int addrlen=s

31、izeof(addrClient);/初始化客户地址长度参数 SockConn=accept(sListen,(SOCKADDR*),在已建立连接的套接字上发送数据send(),函数形式 : int send ( SOCKET s, const char * buf, /用户发送缓冲区指针 int len,/待发送缓冲区的字节数 int flags /一般设置为0表示正常发送数据 );,在已经建立连接的套接字上发送数据。,调用成功:返回发送的字节数。调用失败:返回SOCKET_ERROR,缺省是阻塞函数,在执行send时,若套接字的系统缓冲区没有可用空间,则程序一直阻塞等待,直到有可用的空间为

32、止。,#define BUFFERLEN 1024 /数据缓冲区大小 char sendBufBUFFERLEN;/用户发送缓冲区 sprintf(sendBuf,“欢迎访问我的服务!”); /strlen(buffer)+1 把字符串的结束符0一块发送 int sendlen=send(SockConn,sendBuf,strlen(sendBuf)+1,0);,在已建立连接的套接字上接收数据recv(),函数形式 : int recv (SOCKET s, char * buf, /用户接收缓冲区指针int len, /接收缓冲区的字节数int flags /一般设置为0表示正常接收数据

33、);,对于已经建立连接的套接字, recv可以从该套接字接收数据。,调用成功:返回接收的字节数。调用失败:返回SOCKET_ERROR,缺省是阻塞函数,在执行recv时,若套接字的系统缓冲区没有数据可取,则程序一直阻塞等待,直到接收到对方数据为止。,#define BUFFERLEN 1024 /数据缓冲区大小 char recvBufBUFFERLEN;/用户接收缓冲区 int recvlen=recv(sockClient,recvBuf,sizeof(recvBuf),0);,在无连接的套接字上发送数据sendto(),函数形式 : int sendto (SOCKET s, const

34、 char* buf, /用户发送缓冲区指针int len, /待发送缓冲区的字节数int flags, /一般设置为0 const struct sockaddr* to, /发送数据的目的地址int tolen /目的地址长度 );,对于无连接的套接字,使用sendto()从套接字上发送数据。,调用成功:返回发送的字节数。调用失败:返回SOCKET_ERROR,缺省是阻塞函数,在执行sendto时,如果套接字的系统缓冲区没有可用空间,则程序一直阻塞等待,直到有可用的空间为止。,#define BUFFERLEN 1024 /数据缓冲区大小 char sendBufBUFFERLEN;/用户

35、发送缓冲区 sprintf(sendBuf,“我是张三!“); sendlen=sendto(sockClient,sendBuf,strlen(sendBuf)+1,0, (sockaddr *),在无连接的套接字上接收数据recvfrom(),函数形式 : int recvfrom (SOCKET s, char * buf,/用户接收缓冲区指针int len, /接收缓冲区的字节数int flags,/一般设置为0 struct sockaddr* from, /指明接收数据的来源地址int* fromlen /来源地址长度 );,对于无连接的套接字,使用recvfrom()从套接字上接

36、收一个数据报并保存发送源地址。,调用成功:返回接收的字节数。调用失败:返回SOCKET_ERROR,缺省是阻塞函数,在执行recvfrom时,若套接字的系统缓冲区没有数据可取,则程序一直阻塞等待,直到接收到对方数据为止。,#define BUFFERLEN 1024 /数据缓冲区大小 char recvBufBUFFERLEN;/用户接收缓冲区 SOCKADDR_IN addrClient;/来自客户的地址 int addrlen=sizeof(addrClient);/初始化客户地址长度参数/从客户端接收 recvlen=recvfrom(sockSrv,recvBuf,sizeof(rec

37、vBuf),0, (sockaddr*),4. 数据报套接字编程,用户数据报协议 UDP-特点,UDP 是无连接的,即发送数据之前不需要建立连接(当然发送数据结束时也没有连接可释放),因此减少了开销和发送数据之前的时延。 UDP 使用尽最大努力交付,即不保证可靠交付,同时也不使用拥塞控制,因此主机不需要维持具有许多参数的、复杂的连接状态表。 UDP用户数据报只有 8 个字节的首部开销,比 TCP 的 20 个字节的首部要短。,由于 UDP 没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。这对某些实时应用是很重要的。 UDP 是面向报文的。这就是说,UDP 对应用程序交下来的报文不再

38、划分为若干个分组来发送,也不把收到的若干个报文合并后再交付给应用程序。 应用程序交给 UDP 一个报文,UDP 就发送这个报文;而 UDP 收到一个报文,就把它交付给应用程序。 应用程序必须选择合适大小的报文。,用户数据报协议 UDP-特点,伪首部,源端口,目的端口,长 度,检验和,数 据,首 部,UDP长度,源 IP 地址,目的 IP 地址,0,17,IP 数据报,字节,4,4,1,1,2,12,2,2,2,2,字节,发送在前,数 据,首 部,UDP 用户数据报,UDP 用户数据报的首部格式,伪首部,源端口,目的端口,长 度,检验和,数 据,首 部,UDP长度,源 IP 地址,目的 IP 地

39、址,0,17,IP 数据报,字节,4,4,1,1,2,12,2,2,2,2,字节,发送在前,数 据,首 部,UDP 用户数据报,在计算检验和时,临时把“伪首部”和 UDP 用户数据报连接在一起。伪首部仅仅是为了计算检验和。,数据报套接字,在TCP/IP协议组中,使用UDP协议来实现数据报套接字。,它定义了一种无连接、不可靠的双向数据传输服务。,TCP/IP 协议 架构,TCP,UDP,传输层,应用层,网络层,网络接口层,IP地址定义了某个主机。端口号标识了在此特定主机上的多个进程中的一个。,UDP,UDP,Internet,数据报套接字通信,bind (),recvfrom (),sendto

40、(),closesocket(),socket(),sendto(),recefrom (),closesocket(),socket(),服务器,客户端,创建一个新的套接字,创建一个新的套接字,将一个本地地址关联到一个套接字上,阻塞 等待接收客户数据,发送数据,发送数据,接收数据,关闭套接字,关闭套接字,数据报套接字工作流程(服务器先启动),使用socket()函数创建套接字。 使用bind()函数将创建的套接字与本地地址绑定。 收发数据(sendto()函数recvfrom()函数) 使用closesocket()关闭套接字,客户端工作流程: 使用socket()函数创建套接字。 收发数据

41、(sendto()函数recefrom()函数) 使用closesocket()关闭套接字,服务器端工作流程:,数据报套接字工作流程总结,/ UdpServer.cpp #include / 标准输入输出系统文件 #include / winsock声明文件 #pragma comment(lib, “WS2_32“) / 链接到WS2_32.lib #define PORT 6000 / 此服务器监听的端口号 #define BUFFERLEN 1024 /数据缓冲区大小 void main()/通过载入Winsock库,来使用Winsock的相关函数WSADATA wsaData; /用来

42、返回Winsock库的详细信息 WORD version = MAKEWORD(2, 2); int ret = WSAStartup(version, ,服务器程序:,数据报套接字程序的编写,WSADATA,SOCKET sockSrv; /服务器端套接字/socket(协议地址族,套接字类型,协议); sockSrv=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if ( INVALID_SOCKET =sockSrv) printf(“ 创建套接字失败:%dn“,WSAGetLastError(); return ; sockaddr_in addrSrv

43、; /设置服务器端地址addrSrv.sin_family=AF_INET; /Internet协议地址组addrSrv.sin_port=htons(PORT);/把16位端口转换为网络字节addrSrv.sin_addr.S_un.S_addr=inet_addr(“192.168.0.1“);/ 指定IP/绑定套接字到服务器端地址 /bind(服务器端套接字,服务器端地址,服务器端地址长度); if(SOCKET_ERROR= bind(sockSrv,(sockaddr *),sockaddr_in,SOCKADDR_IN addrClient;/声明来自客户的地址,以备填充 int

44、addrlen=sizeof(addrClient);/初始化客户地址长度参数char sendBufBUFFERLEN;/用户发送缓冲区char recvBufBUFFERLEN;/用户接收缓冲区int sendlen; int recvlen;/发送接收数据长度while (true) /进入循环/从客户端接收/recvfrom(服务器端套接字,接收缓冲区,缓冲区大小,接收标志, 接收数据的来源地址,来源地址长度) recvlen=recvfrom(sockSrv,recvBuf,sizeof(recvBuf),0, (sockaddr *),/向客户端发送sprintf(sendBuf,

45、“欢迎IP%s;端口%d访问我的服务!”, inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port);/sendto(服务器端套接字,发送缓冲区,发送数据长度,发送标志, 发送数据的目的地址,目的地址长度);/strlen(sendBuf)+1 指把结束符0一块发送 sendlen=sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0, (sockaddr *) /释放Winsock库 ,/ UdpClient.cpp #include / 标准输入输出系统文件 #include / winsock声明

46、文件 #pragma comment(lib, “WS2_32“) / 链接到WS2_32.lib #define PORT 6000 / 此服务器监听的端口号 #define BUFFERLEN 1024 /数据缓冲区大小 void main()/通过载入Winsock库,来使用Winsock的相关函数WSADATA wsaData; /用来返回Winsock库的详细信息 WORD version = MAKEWORD(2, 2); int ret = WSAStartup(version, ,客户端程序:,SOCKET sockClient; /声明客户端套接字/socket(协议地址族,

47、套接字类型,协议); sockClient=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if ( INVALID_SOCKET =sockClient) printf(“ 创建套接字失败:%dn“,WSAGetLastError(); return ; / 填写远程地址信息sockaddr_in addrSrv;/声明服务器端地址addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(PORT);/把16位端口号转换为网络字节addrSrv.sin_addr.S_un.S_addr=inet_addr(“192.168.0.1“); int addrlen=sizeof(addrSrv);/初始化服务器端地址长度参数,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报