WinSocket编程

上传人:hjk****65 文档编号:178144614 上传时间:2022-12-27 格式:DOC 页数:24 大小:118KB
收藏 版权申诉 举报 下载
WinSocket编程_第1页
第1页 / 共24页
WinSocket编程_第2页
第2页 / 共24页
WinSocket编程_第3页
第3页 / 共24页
资源描述:

《WinSocket编程》由会员分享,可在线阅读,更多相关《WinSocket编程(24页珍藏版)》请在装配图网上搜索。

1、WinSocket编程默认分类 2009-12-07 10:33:56 阅读164 评论0 字号:大中小 什么是Socket接触网络编程当然要了解Socket,Socket(套接字)是一种网络编程接口,Socket提供了很多灵活的函数,帮助程序员写出高效的网络应用。Socket分为BSD UNIX和windows两个版本。在win32平台上的Winsock编程都要经过下列基本步骤:定义变量获得Winsock版本加载Winsock库初始化创建套接字设置套接字关闭套接字卸载Winsock库使用winsock2 API编程,必须包含头文件winsock2.h (链接环境WS2_32.LIB),头文件

2、winsock.h(WSOCK32.LIB)是为了兼容winsock1程序时使用的,另外mswsock.h(MSWSOCK.DLL)是微软的扩展类,用于开发高性能的winsock程序。准备好后,你就可以着手建立你的第一个网络程序了。二, Socket编程的基本过程Socket通信分为面向连接的通信(TCP)和面向无连接的通信(UDP),通信流程如下: 面向连接的通信 无连接的通信1,Winsock初始化和结束每一个winsock应用程序必须首先加载相应的winsock dll版本。方法是调用:int WSAStartup( WORD wVersionRequested, 库版本,高字节副版本,

3、低字节主版本 LPWSADATA lpWSAData 结构指针,函数自动填充该结构。); 函数调用成功返回0可以用宏MAKEWORD(x, y)用来指定第一个参数的值 2,建立套接字套接字是传输提供者的一个句柄。SOCKET socket ( int af, int type, int protocol IPPROTO_TCP, IPPROTO_UDP, 0(如果不想指定));第一个参数指定通信协议的协议族,AF_INET(IPv4)或 AF_INET6(IPv6)(因为Socket是网络编程接口而不是一个协议,它使用流行的网络协议(TCP/IP,IPX)为应用程序提供的一个编程接口。)第二个

4、参数指定要创建的套接字的类型。SOCK_STREAM(TCP流套接字), SOCK_ DGRAM(UDP 数据包套接字),SOCK_RAW(原始套接字)第三个参数指定应用程序所指定应用程序所使用的通信协议。函数成功返回套接字描述符,失败返回INVALID_SOCKET 3,配置套接字当创建一个套接字后,再进行网络通信之前,必须先配置Socket。面向连接的客户端Socket通过调用connect函数在Socket数据结构中保存地址和远端信息。无连接客户端,服务端以及面向连接Socket的服务端,通过调用bind函数来配置本地信息。int bind( SOCKET s, 创建的套接字 const

5、 struct sockaddr FAR* name, 指向地址缓冲区的指针 int namelen 地址缓冲区的大小);成功返回0,失败返回SOCKET_ERROR当创建一个套接字后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。第二个参数指定一个sockaddr结构定义如下:struct sockaddr u_short sa_family; char sa_data14;我们通常使用另外一个等价的地址结构:struct sockaddr_in short sin_family; u_short sin_por

6、t; struct in_addr sin_addr; char sin_zero8;其中sin_family是通信协议族,sin_port指明端口号,sin_addr结构中有一个字段s_addr,表示IP地址,该字段是一个整数,一般用函数inet_addr把点分字符串形式的IP地址转化成unsigned long型的整数值。如果指定为htonl(INADDR_ANY),那么无论哪个网段上的客户机都能与该服务器通信,否则,只有与指定IP地址处于同一网段上的客户机能与该服务器通信。sin_zero8为填充,使两个结构大小相同。 有一些细节学要说明: 在计算机把IP地址和端口号指定成多字节时,这个

7、数是按“主机字节”(host-byte)顺序表示的,不同的处理器对数的表示方法有“大头”(big-endian最有意义的字节到最无意义的字节)和“小头”(little-endian)两种形式。但是如果在网络上指定IP地址和端口号时,必须按照big-endian 的形式,一般称之为“网络字节”(network-byte)顺序。以下几个函数将主机字节顺序转换成网络字节顺序:u_long htonl(u_long hostlong); int WSAHtonl( SOCKET s, u_long hostlong, u_long FAR * lpnetlong 通过指针返回网络字节顺序的4个字节的数

8、); u_short htons(u_short hostshort); int WSAHtons( SOCKET s, u_short hostshort, u_short FAR * lpnetshort 通过指针返回网络字节顺序的2个字节的数);以下几个函数将网络字节顺序转换成主机字节顺序:u_long ntohl(u_long netlong); int WSANtohl( SOCKET s, u_long netlong, u_long FAR * lphostlong); u_short ntohs(u_short netshort); int WSANtohs( SOCKET s

9、, u_short netshort, u_short FAR * lphostshort); 4,实现功能(1) 服务器端: 需要对绑定的端口进行侦听,函数原型如下 int listen ( SOCKETs, intbacklog ); Backlog是客户连接请求队列的最大数量,而不是客户机连接的数量限制。处于侦听的套接字将维护一个客户连接请求队列。 该函数执行成功返回0,失败返回SOCKET_ERROR 此外,需要从连接请求队列中取出最前面的一个客户请求,需要用到accept()函数: SOCKET accept ( SOCKETs, struct sockaddr FAR*addr,

10、int FAR*addrlen );该函数创建一个新的套接字来与客户套接字建立通信,如果连接成功,就返回新建的套接字描述符,以后与客户通信的就是该套接字,而侦听套接字则继续接受新的连接;如果失败就返回INVALID_SOCKET第一个参数是侦听套接字第二个套接字用来返回新创建的套接字的地址结构第三个套接字返回地址结构的长度 (2) 客户端:connect函数是客户机建立与远程服务器连接而使用的。int connect ( SOCKETs, const struct sockaddr FAR* name, intnamelen ); 5,数据传输 收发数据时网络编程的一切在这里我们只讨论同步函数

11、send和recv,不讨论异步函数WSASend和WSARecv。数据发送要用到send函数,原型如下:int send( SOCKET s, const char FAR * buf, 发送数据缓冲区的地址 int len, 要发送的字节数 int flags 一般为0, MSG_DONTROUTE, MSG_OOB(外带数据));成功返回发送字节数,出错返回SOCKET_ERROR注意send函数把数据从buf复制到socket发送缓冲区后就返回了,但是这些数据并不时马上就发送到连接的另一端。 在已连接的套接字上接受数据,recv函数是最基本的方式。int recv( SOCKET s,

12、char FAR* buf, int len, 准备接收的字节数或buf缓冲区长度 int flags 0, MSG_PEEK, MSG_OOB 其中MSG_PEEK表示将有用的数据复制到所提供的接收端缓冲区,但是没有从系统缓冲区中将它删除);成功返回接收的数据的字节数量,失败返回SOCKET_ERROR,如果接受数据时网络中断返回0 6,关闭Socket一旦完成任务,记得将套接字关闭以释放资源: int closeSocket(SOCKET s)三, Socket编程实例 讲了这么多其实还是看实例最为重要了,下面我提供了最简单的面向连接的客户端和服务端程序,当服务端接受客户端的连接后,先是该

13、客户机地IP地址,并向客户端发送一个回应消息,最后关闭该连接套接字。这样的服务器当然没什么实际的用途。设计一个基本的网络服务器有以下几个步骤:1、初始化Windows Socket2、创建一个监听的Socket3、设置服务器地址信息,并将监听端口绑定到这个地址上4、开始监听5、接受客户端连接6、和客户端通信7、结束服务并清理Windows Socket和相关数据,或者返回第4步 #include #include #define SERVPORT 5050#pragma comment(lib,ws2_32.lib) void main(void) WSADATA wsaData; SOCKE

14、T sListen; / 监听socket SOCKET sClient; / 连接socket SOCKADDR_IN serverAddr; / 本机地址信息 SOCKADDR_IN clientAddr; / 客户端地址信息 int clientAddrLen; / 地址结构的长度 int nResult; / 初始化Windows Socket 2.2 WSAStartup(MAKEWORD(2,2), &wsaData); / 创建一个新的Socket来响应客户端的连接请求 sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /

15、填写服务器绑定的地址信息 / 端口为5150 / IP地址为INADDR_ANY,响应每个网络接口的客户机活动 / 注意使用htonl将IP地址转换为网络格式 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SERVPORT); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); memset(&(serverAddr.sin_zero), 0, sizeof(serverAddr.sin_zero); / 绑定监听端口 nResult = bind(sListen, (SOC

16、KADDR *)&serverAddr, sizeof(SOCKADDR); if (nResult = SOCKET_ERROR) printf(bind failed!n); return; / 开始监听,指定最大接受队列长度5,不是连接数的上限 listen(sListen, 5); / 接受新的连接 while(1) clientAddrLen = sizeof (SOCKADDR); sClient = accept(sListen, (SOCKADDR *)&clientAddr, &clientAddrLen); if(sClient = INVALID_SOCKET) prin

17、tf(Accept failed!); else printf(Accepted client: %s : %dn, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port); / 向客户端发送信息 nResult = send(sClient, Connect success!, 16, 0); if (nResult = SOCKET_ERROR) printf(send failed!); / 我们直接关闭连接, closesocket(sClient); / 并关闭监听Socket,然后退出应用程序 closesocket(s

18、Listen); / 释放Windows Socket DLL的相关资源 WSACleanup(); 客户机程序如下:#include #include #define SERVPORT 5050 / 端口为5150#define MAXDATASIZE 100#define SERVIP 127.0.0.1 / 服务器IP地址为127.0.0.1,注意使用inet_addr将IP地址转换为网络格式#pragma comment(lib,ws2_32.lib) void main(int argc, char *argv) WSADATA wsaData; SOCKET sConnect; S

19、OCKADDR_IN serverAddr; int recvbytes; char bufMAXDATASIZE; /初始化Windows Socket 2.2 WSAStartup(MAKEWORD(2,2), &wsaData); / 创建一个新的Socket来连接服务器 sConnect = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); / 填写连接地址信息 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SERVPORT); serverAddr.sin_addr.s_a

20、ddr = inet_addr(SERVIP); memset(&(serverAddr.sin_zero), 0, sizeof(serverAddr.sin_zero); / 向服务器发出连接请求 if (connect(sConnect, (SOCKADDR *)&serverAddr, sizeof(SOCKADDR) = SOCKET_ERROR) printf(connect failed!n); return; / 接受服务器的回应消息 recvbytes = recv(sConnect, buf, MAXDATASIZE, 0); if (recvbytes = SOCKET_

21、ERROR) printf(recv failed!n); else bufrecvbytes = 0; printf(%sn,buf); closesocket(sConnect); / 释放Windows Socket DLL的相关资源 WSACleanup(); 四, 结束语这里介绍的只不过是winsock最基础最基础的知识,开发网络程序从来都不是一件容易的事情,尽管只需要遵守很少的一些规则: 创建套接字,发起连接,接受连接,发送和接受数据。真正的困难在于:让你的程序可以适应从单单一个连接到几千个连接,即开发一个大容量,具可扩展性的Winsock应用程序。Winscok编程很重要的一部分是IO处理,分别提供了“套接字模式”和“套接字I/O模型”,可对一个套接字上的I/O行为进行控制。其中,套接字模式用于决定在随一个套接字调用时,那些Winsock函数的行为,有阻塞和非阻塞两种模式。而另一方面,套接字模型描述了一个应用程序如何对套接字上进行的I/O进行管理及处理,包括包括Select,WSAAsyncSelect,WSAEventSelect ,IO重叠模型,完成端口等。在这里推荐一本好书windows网络编程技术,有兴趣研究的同志可以去啃一啃。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!