Socket编程指南及示例程序.pdf
《Socket编程指南及示例程序.pdf》由会员分享,可在线阅读,更多相关《Socket编程指南及示例程序.pdf(23页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、1前言在一些常用的编程技术中,Socket网络编程可以说是最简单的一种。而且Socket编程需要的基础知识很少,适合初学者学习网络编程。目前支持网络传输的技术、语言和工具繁多,但是大部分都是基于Socket开发的,虽说这些“高级”的网络技术屏蔽了大部分底层实现,号称能极大程度的简化开发,而事实上如果你没有一点Socket基础,要理解和应用这些技术还是很困难的,而且会让你成为“半瓢水”。深有感触的是当年我学习CORBA 的时候,由于当时各方面的基础薄弱,整整啃了半年书,最终还是一头雾水。如果现在让我带一个人学CORBA,我一定会安排好顺序:首先弄清C+语法;然后是VC 编译环境或者nmake的用
2、法;接下来学习一些网络基础知识;然后是 Socket编程;这些大概要花费3、4 个月。有了这些基础学习CORBA 一周即可弄懂,两个月就可以基于CORBA 进行开发了。好了,说了半天其实中心思想就一个,Socket很简单,很好学!如果你会 C+或者 JAVA,又懂一点点网络基础如TCP 和 UDP 的机制,那么你看完本文就可以熟练进行Socket开发了。2Socket简介(全文摘抄)(本节内容全部抄自网络,不保证正确性,有兴趣的可以看看!)80 年代初,美国政府的高级研究工程机构(ARPA)给加利福尼亚大学Berkeley分校提供了资金,让他们在UNIX操作系统下实现TCP/IP 协议。在这个
3、项目中,研究人员为TCP/IP网络通信开发了一个API(应用程序接口)。这个API 称为 Socket接口(套接字)。今天,SOCKET接口是 TCP/IP 网络最为通用的API,也是在 INTERNET上进行应用开发最为通用的API。90 年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口,即 WindowsSockets规范。它是BerkeleySockets的重要扩充,主要是增加了一些异步函数,并增加了符合Windows消息驱动特性的网络事件异步选择机制。WINDOWSSOCKETS规范是一套开放的、支持多种协议的Windows下的网络编程接口。从
4、 1991年的 1.0 版到 1995年的 2.0.8版,经过不断完善并在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的全力支持下,已成为Windows网络编程的事实上的标准。目前,在实际应用中的WINDOWSSOKCETS规范主要有1.1 版和 2.0 版。两者的最重要区别是1.1版只支持 TCP/IP协议,而 2.0版可以支持多协议。2.0版有良好的向后兼容性,任何使用1.1 版的源代码,二进制文件,应用程序都可以不加修改地在2.0 规范下使用。SOCKET实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有SOCKET接口的计算机通信。
5、应用程序在网络上传输,接收的信息都通过这个SOCKET接口来实现。在应用开发中就像使用文件句柄一样,可以对SOCKET句柄进行读,写操作。3再说两句网上很多文章对于Socket的来龙去脉有如教科书一般的精准。但是涉及具体编程技术就往往被 VC 等集成开发环境所毒害了,把Windows SDK、MFC、Socket、多线程、DLL 以及编译链接等等技术搅合在一起煮成一锅夹生饭。既然要学习Socket,就应该用最简单直白的方式把Socket的几个使用要点讲出来。我认为程序员最关心的有以下几点,按照优先级排列如下:1.Socket的机制是什么?2.用 C/C+写 Socket需要什么头文件、库文件、
6、DLL,它们可以由谁提供,安装后一般处于系统的哪个文件夹内?3.编写 Socket程序需要的编程基础是什么?4.Socket库内最重要的几个函数和数据类型是什么?5.两个最简单的例子程序;6.一个贴近应用的稍微复杂的Socket应用程序。我将一一讲述这些要点,并给出从简到繁,从朴素到花哨的所有源代码以及编译链接的命令。4Socket的机制是什么?我们可以简单的把Socket理解为一个可以连通网络上不同计算机程序之间的管道,把一堆数据从管道的A 端扔进去,则会从管道的B 端(也许同时还可以从C、D、E、F 端冒出来)。管道的端口由两个因素来唯一确认,即机器的IP 地址和程序所使用的端口号。IP
7、地址的含义所有人都知道,所谓端口号就是程序员指定的一个数字,许多著名的木马程序成天在网络上扫描不同的端口号就是为了获取一个可以连通的端口从而进行破坏。比较著名的端口号有 http的 80 端口和 ftp 的 21 端口(我记错了么?)。当然,建议大家自己写程序不要使用太小的端口号,它们一般被系统占用了,也不要使用一些著名的端口,一般来说使用10005000之内的端口比较好。Socket可以支持数据的发送和接收,它会定义一种称为套接字的变量,发送数据时首先创建套接字,然后使用该套接字的sendto等方法对准某个IP/端口进行数据发送;接收端也首先创建套接字,然后将该套接字绑定到一个IP/端口上,
8、所有发向此端口的数据会被该套接字的 recv等函数读出。如同读出文件中的数据一样。5所需的头文件、库文件和DLL 对于目前使用最广泛的Windows Socket2.0版本,所需的一些文件如下(以安装了VC6为例说明其物理位置):头文件 winsock2.h,通常处于C:Program FilesMicrosoft Visual StudioVC98INCLUDE;查看该头文件可知其中又包含了windows.h和pshpack4.h头文件,因此在windows中的一些常用API 都可以使用;库文件 Ws2_32.lib,通常处于C:Program FilesMicrosoft Visual S
9、tudioVC98Lib;DLL 文件 Ws2_32.dll,通常处于C:WINDOWSsystem32,这个是可以猜到的。6编写 Socket程序需要的编程基础在开始编写Socket程序之前,需要以下编程基础:C+语法;一点点 windows SDK 的基础,了解一些 SDK 的数据类型与API 的调用方式;一点点编译、链接和执行的技术;知道cl 和 link 的最常用用法即可。7UDP 用最通俗的话讲,所谓 UDP,就是发送出去就不管的一种网络协议。因此 UDP 编程的发送端只管发送就可以了,不用检查网络连接状态。下面用例子来说明怎样编写UDP,并会详细解释每个API 和数据类型。7.1
10、UDP广播发送程序下面是一个用UDP 发送广播报文的例子。#include#include void main()SOCKET sock;/socket套接字char szMsg=this is a UDP test package;/被发送的字段/1.启动 SOCKET库,版本为2.0 WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested=MAKEWORD(2,0);err=WSAStartup(wVersionRequested,&wsaData);if(0!=err)/检查 Socket初始化是否成功 coutS
11、ocket2.0初始化失败,Exit!;return;/检查 Socket库的版本是否为2.0 if(LOBYTE(wsaData.wVersion)!=2|HIBYTE(wsaData.wVersion)!=0)WSACleanup();return;/2.创建 socket,sock=socket(AF_INET,/internetwork:UDP,TCP,etc SOCK_DGRAM,/SOCK_DGRAM说明是 UDP 类型0 /protocol);if(INVALID_SOCKET=sock)coutSocket 创建失败,Exit!;return;/3.设置该套接字为广播类型,bo
12、ol opt=true;setsockopt(sock,SOL_SOCKET,SO_BROADCAST,reinterpret_cast(&opt),sizeof(opt);/4.设置发往的地址sockaddr_in addrto;/发往的地址memset(&addrto,0,sizeof(addrto);addrto.sin_family=AF_INET;/地址类型为internetwork addrto.sin_addr.s_addr=INADDR_BROADCAST;/设置 ip 为广播地址addrto.sin_port=htons(7861);/端口号为7861 int nlen=si
13、zeof(addrto);unsigned int uIndex=1;while(true)Sleep(1000);/程序休眠一秒/向广播地址发送消息if(sendto(sock,szMsg,strlen(szMsg),0,(sockaddr*)&addrto,nlen)=SOCKET_ERROR)coutWSAGetLastError()endl;else coutuIndex+:an UDP package is sended.UDP_Send_Broadcast.exe 1:an UDP package is sended.2:an UDP package is sended.3:an
14、UDP package is sended.4:an UDP package is sended.C 下面一一解释代码中出现的数据类型与API 函数。有耐心的可以仔细看看,没耐心的依葫芦画瓢也可以写程序了。7.2 SOCKET类型SOCKET是 socket套接字类型,在WINSOCK2.H中有如下定义:typedef unsigned int u_int;typedef u_int SOCKET;可知套接字实际上就是一个无符号整型,它将被 Socket环境管理和使用。套接字将被创建、设置、用来发送和接收数据,最后会被关闭。7.3 WORD类型、MAKEWORD、LOBYTE和 HIBYTE宏
15、WORD类型是一个16 位的无符号整型,在WTYPES.H中被定义为:typedef unsigned short WORD;其目的是提供两个字节的存储,在 Socket中这两个字节可以表示主版本号和副版本号。使用 MAKEWORD宏可以给一个WORD类型赋值。例如要表示主版本号2,副版本号0,可以使用以下代码:WORD wVersionRequested;wVersionRequested=MAKEWORD(2,0);注意低位内存存储主版本号2,高位内存存储副版本号0,其值为 0 x0002。使用宏 LOBYTE可以读取 WORD的低位字节,HIBYTE可以读取高位字节。7.4 WSADAT
16、A类型和 LPWSADATA类型WSADATA类型是一个结构,描述了Socket库的一些相关信息,其结构定义如下:typedef struct WSAData WORD wVersion;WORD wHighVersion;char szDescriptionWSADESCRIPTION_LEN+1;char szSystemStatusWSASYS_STATUS_LEN+1;unsigned short iMaxSockets;unsigned short iMaxUdpDg;char FAR*lpVendorInfo;WSADATA;typedef WSADATA FAR*LPWSADAT
17、A;值得注意的就是wVersion字段,存储了 Socket的版本类型。LPWSADATA是 WSADATA的指针类型。它们不用程序员手动填写,而是通过Socket的初始化函数WSAStartup读取出来。7.5 WSAStartup函数WSAStartup函数被用来初始化Socket环境,它的定义如下:int PASCAL FAR WSAStartup(WORD wVersionRequired,LPWSADATA lpWSAData);其返回值为整型,调用方式为PASCAL(即标准类型,PASCAL等于_stdcall),参数有两个,第一个参数为WORD类型,指明了Socket的版本号,第
18、二个参数为WSADATA类型的指针。若返回值为0,则初始化成功,若不为0 则失败。7.6 WSACleanup函数这是 Socket环境的退出函数。返回值为0 表示成功,SOCKET_ERROR表示失败。7.7 socket函数socket的创建函数,其定义为:SOCKET PASCAL FAR socket(int af,int type,int protocol);第一个参数为int af,代表网络地址族,目前只有一种取值是有效的,即AF_INET,代表internet地址族;第二个参数为int type,代表网络协议类型,SOCK_DGRAM代表 UDP 协议,SOCK_STREAM代表
19、 TCP 协议;第三个参数为int protocol,指定网络地址族的特殊协议,目前无用,赋值0 即可。返回值为SOCKET,若返回INVALID_SOCKET则失败。7.8 setsockopt函数这个函数用来设置Socket的属性,若不能正确设置socket属性,则数据的发送和接收会失败。定义如下:int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char FAR*optval,int optlen);其返回值为int 类型,0 代表成功,SOCKET_ERROR代表有错误发生。第一个参数SOCKET s,代表要设
20、置的套接字;第二个参数int level,代表要设置的属性所处的层次,层次包含以下取值:SOL_SOCKET代表套接字层次;IPPROTO_TCP代表 TCP 协议层次,IPPROTO_IP代表 IP 协议层次(后面两个我都没有用过);第三个参数int optname,代表设置参数的名称,SO_BROADCAST代表允许发送广播数据的属性,其它属性可参考MSDN;第四个参数const char FAR*optval,代表指向存储参数数值的指针,注意这里可能要使用 reinterpret_cast类型转换;第五个参数int optlen,代表存储参数数值变量的长度。7.9 sockaddr_in
21、、in_addr类型,inet_addr、inet_ntoa函数sockaddr_in定义了 socket发送和接收数据包的地址,定义:struct sockaddr_in short sin_family;u_short sin_port;struct in_addr sin_addr;char sin_zero8;其中 in_addr的定义如下:struct in_addr union struct u_char s_b1,s_b2,s_b3,s_b4;S_un_b;struct u_short s_w1,s_w2;S_un_w;u_long S_addr;S_un;首先阐述in_addr
22、的含义,很显然它是一个存储ip 地址的联合体(忘记 union含义的请看c+书),有三种表达方式:第一种用四个字节来表示IP 地址的四个数字;第二种用两个双字节来表示IP 地址;第三种用一个长整型来表示IP 地址。给 in_addr赋值的一种最简单方法是使用inet_addr函数,它可以把一个代表IP 地址的字符串赋值转换为in_addr类型,如addrto.sin_addr.s_addr=inet_addr(192.168.0.2);本例子中由于是广播地址,所以没有使用这个函数。其反函数是inet_ntoa,可以把一个in_addr类型转换为一个字符串。sockaddr_in的含义比in_a
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Socket 编程 指南 示例 程序
限制150内