VisualC网络编程案例实战之Socket套接字编程.pptx

上传人:wj 文档编号:18071493 上传时间:2023-08-10 格式:PPTX 页数:105 大小:3.52MB
下载 相关 举报
VisualC网络编程案例实战之Socket套接字编程.pptx_第1页
第1页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第2页
第2页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第3页
第3页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第4页
第4页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第5页
第5页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第6页
第6页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第7页
第7页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第8页
第8页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第9页
第9页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第10页
第10页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第11页
第11页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第12页
第12页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第13页
第13页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第14页
第14页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第15页
第15页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第16页
第16页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第17页
第17页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第18页
第18页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第19页
第19页 / 共105页
VisualC网络编程案例实战之Socket套接字编程.pptx_第20页
第20页 / 共105页
亲,该文档总共105页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

VisualC网络编程案例实战之Socket套接字编程.pptx

《VisualC网络编程案例实战之Socket套接字编程.pptx》由会员分享,可在线阅读,更多相关《VisualC网络编程案例实战之Socket套接字编程.pptx(105页珍藏版)》请在冰点文库上搜索。

VisualC网络编程案例实战之Socket套接字编程.pptx

第2章Socket套接字编程,套接字是由美国伯克利大学提出并设计的一种在网络中不同主机之间进行数据交换的通信桥梁。

在实际生活中,人们所使用的网络通信软件功能均是基于Socket套接字作为通信桥梁实现。

所以,套接字在网络编程中,有着非常重要的作用。

本章将向用户介绍使用Socket套接字编程的相关概念以及实现方法。

2.1寻址方式和字节顺序,在讲解套接字编程前,用户需要首先了解一下什么是寻址方式和字节顺序。

在Socket套接字编程中,为了准确定位通信双方和数据传输的有效性、完整性,编程时必须使用统一的寻址方式和字节排列顺序。

2.1.1寻址方式,因为套接字需要在各种网络协议中使用,所以为了区分程序所使用的网络协议必须使用统一的寻址方式。

例如,在TCP/IP协议通信中,用户使用IP地址和端口号进行确定通信双方。

而在其他的协议中不一定也使用该方式确定通信双方。

在Winsock(SocketAPI)中,用户可以使用TCP/IP地址家族中统一的套接字地址结构解决TCP/IP寻址中可能出现的问题。

该套接字地址结构定义如下:

structsockaddr_inshortsin_family;/指定地址家族即地址格式unsignedshortsin_port;/端口号码structin_addrsin_addr;/IP地址charsin_zero8;/需要指定为0;,在这个结构中,成员sin_family指定使用该套接字地址的地址家族。

在这里必须设置为AF_INET,表示程序所使用的地址家族是TCP/IP。

注意:

该结构的最后一个成员并未实际使用,主要是为了与第一个版本的套接字地址结构大小相同而设置。

在实际使用时,将这8个字节直接设为0即可。

该结构成员变量sin_addr表示32位的IP地址结构。

其结构定义如下:

structin_addrunionstructunsignedchars_b1,s_b2,s_b3,s_b4;S_un_b;/用4个u_char字符描述IP地址structunsignedshorts_w1,s_w2;S_un_w;/用2个u_short类型描述IP地址unsignedlongS_addr;/用1个u_long类型描述IP地址S_un;,通常,用户在网络编程中使用1个u_long类型的字符进行描述IP地址即可。

例如,使用IP地址结构in_addr进行描述IP地址“218.6.132.5”。

代码如下:

sockaddr_inaddr;addr.sin_addr.S_un.S_addr=inet_addr(218.6.132.5);在程序中,首先定义sockaddr_in结构对象addr,然后为IP地址结构in_addr中的成员S_addr赋值。

因为结构成员S_addr所描述的IP地址均为网络字节顺序,所以程序调用inet_addr()函数将字符串IP转换为以网络字节顺序排列的IP地址。

2.1.2字节顺序,在Socket套接字编程中,传输数据的排列顺序以网络字节顺序和主机字节顺序为主。

通常情况下,如果用户将数据通过网络发送时,需要将数据转换成以网络字节顺序排列,否则可能造成数据损坏。

如果用户是将网络中接收到的数据存储在本地计算机上,那么需要将数据转换成以主机字节顺序排列。

从数据存储的角度来讲,网络字节顺序即将数据中最重要的字节首先进行存储,而主机字节顺序则将不重要的字节首先存储。

注意:

IP地址结构in_addr中的成员S_addr的值均是以网络字节顺序排列。

1字节顺序转换函数,在Winsock中提供了几个关于网络字节顺序与主机字节顺序之间的转换函数。

函数定义如下:

/将一个u_short类型的IP地址从主机字节顺序转换到网络字节顺序u_shorthtons(u_shorthostshort);/将一个u_long类型的IP地址从主机字节顺序转换到网络字节顺序u_longhtonl(u_longhostlong);/将一个u_long类型的IP地址从网络字节顺序转换到主机字节顺序u_longntohl(u_longnetlong);/将一个u_short类型的IP地址从网络字节顺序转换到主机字节顺序u_shortntohs(u_shortnetshort);/将一个字符串IP转换到以网络字节顺序排列的IP地址unsignedlonginet_addr(constcharFAR*cp);/将一个以网络字节顺序排列的IP地址转换为一个字符串IPcharFAR*inet_ntoa(structin_addrin);以上函数的使用均与操作系统平台无关。

因此,用户使用这些函数编写的程序能在所有操作系统平台中运行。

2实例程序,在本节中,将编写实例程序向用户讲解字节顺序转换函数的用法。

代码如下:

./省略部分代码sockaddr_inaddr;/定义套接字地址结构变量addr.sin_family=AF_INET;/指定地址家族为TCP/IPaddr.sin_port=htons(80);/指定端口号/将字符串IP转换为网络字节顺序排列的IPaddr.sin_addr.S_un.S_addr=inet_addr(127.0.0.1);/将网络字节顺序排列的IP转换为字符串IPcharaddres=inet_ntoa(addr.sin_addr.S_un.S_addr);,在程序中,用户首先使用函数inet_addr()将字符串IP“127.0.0.1”转换为以网络字节顺序排列的IP并保存在IP地址结构成员S_addr中。

然后,再使用函数inet_ntoa()则将该成员所表示的IP值转换成字符串IP。

2.1.3Socket相关函数,由于Windows网络程序开发均是基于Windows套接字实现,所以本节将重点介绍MFC中的CSocket类以及使用CSocket类编程的基本流程。

1创建套接字,使用CSocket类创建套接字对象是通过该类的构造函数创建的。

其原型如下:

CSocket:

CSocket();例如,用户创建CSocket类对象,代码如下:

CSocketsock;如果用户需要创建套接字对象指针,则应该使用关键字new进行创建。

代码如下:

CSocket*sock;/定义套接字指针对象sock=newCSocket;/使用new关键字创建套接字,2绑定地址信息,如果用户创建服务器套接字,那么用户应该调用该类的函数Bind()将套接字对象与服务器地址信息绑定在一起。

其原型如下:

BOOLBind(constSOCKADDR*lpSockAddr,intnSockAddrLen);该函数的作用是将套接字对象与服务器地址结构绑定在一起。

如果函数调用成功,则返回true。

否则,返回false。

参数lpSockAddr指定将要绑定的服务器地址结构,参数nSockAddrLen表示地址结构的长度。

例如,用户将上面创建的套接字对象与地址结构绑定。

代码如下:

CSocketsock;/创建套接字对象sockaddr_inaddr;/定义套接字地址结构变量addr.sin_family=AF_INET;/指定地址家族为TCP/IPaddr.sin_port=htons(80);/指定端口号/将字符串IP转换为网络字节顺序排列的IPaddr.sin_addr.S_un.S_addr=inet_addr(127.0.0.1);sock.Bind(SOCKADDR*)addr,sizeof(addr);/绑定套接字与地址结构./省略部分代码,在服务器端,当地址信息绑定套接字成功后,还需要调用函数Listen()在指定端口监听客户端的连接请求。

函数Listen()的原型如下:

BOOLListen(intnConnectionBacklog=5);参数nConnectionBacklog表示套接字监听客户端请求的最大数目。

该参数的有效范围是15。

默认为5,表示该套接字只能监听5个客户端所发送的连接请求。

例如,套接字监听5个客户端的连接请求,代码如下:

CSocketsock;/创建套接字对象sockaddr_inaddr;/定义套接字地址结构变量addr.sin_family=AF_INET;/指定地址家族为TCP/IPaddr.sin_port=htons(80);/指定端口号/将字符串IP转换为网络字节顺序排列的IPaddr.sin_addr.S_un.S_addr=inet_addr(127.0.0.1);sock.Bind(SOCKADDR*)addr,sizeof(addr);/绑定套接字与地址结构sock.Listen(5);/监听端口,3连接服务器,客户端创建套接字成功以后,可以调用函数Connect()向服务器发送连接请求。

函数原型如下:

BOOLConnect(constSOCKADDR*lpSockAddr,intnSockAddrLen);该函数调用成功,则返回true。

否则,将返回false。

参数lpSockAddr表示将连接的服务器地址结构。

参数nSockAddrLen表示地址结构的长度大小。

例如,服务器IP地址为“127.0.0.1”,端口为80,客户端连接服务器,代码如下:

CSocketsock;/创建套接字对象sockaddr_inaddr;/定义套接字地址结构变量addr.sin_family=AF_INET;/指定地址家族为TCP/IPaddr.sin_port=htons(80);/指定端口号/将字符串IP转换为网络字节顺序排列的IPaddr.sin_addr.S_un.S_addr=inet_addr(127.0.0.1);sock.Connect(SOCKADDR*)addr,sizeof(addr);/连接服务器,4数据交换,无论是服务器,还是客户端都是通过函数Send()和Receive()进行数据交换。

函数原型如下:

virtualintSend(constvoid*lpBuf,intnBufLen,intnFlags=0);virtualintReceive(void*lpBuf,intnBufLen,intnFlags=0);其中,函数Send()用于发送指定缓冲区的数据,函数Receive()用于接收对方发送的数据,并将数据存放在指定缓冲区中。

参数lpBuf表示数据缓冲区地址。

参数nBufLen表示数据缓冲区的大小。

参数nFlags表示数据发送或接收的标志,一般情况下,该参数均设置为0。

例如,使用这两个函数进行数据的发送和接收。

代码如下:

./省略部分代码charbuff=a;/定义并初始化数据缓冲区sock.Send(/接收数据并将数据存放在数据缓冲区中,5关闭套接字对象,当服务器和客户端的通信完成以后,用户还必须调用函数Close()将套接字对象关闭。

否则,程序可能在退出时发生错误。

该函数原型如下:

virtualvoidClose();例如,客户端关闭套接字对象,代码如下:

./省略部分代码sock.Close();/关闭套接字对象套接字关闭的同时,也将服务器与客户端之间连接关闭了。

本节主要向用户介绍了CSocket类的常用函数以及用法。

当用户创建VC应用程序时,如果没有为应用程序指定支持WindowsSocket,那么用户必须手动添加该类的头文件afxsock.h。

否则,程序将不能使用CSocket类。

2.2Winsock网络程序开发流程,本节将向用户讲述基于WindowsSocket的应用程序开发步骤,并将编写实例程序向用户介绍网络应用程序的开发过程以及CSocket类的具体使用方法。

本节中的实例程序均在VC中进行编写、调试。

2.2.1VC中创建工程的步骤,用户在VC中使用应用程序向导创建基于套接字的应用程序工程时,必须为该应用程序指定支持WindowsSocket功能。

否则,创建的应用程序不能进行网络通信。

如果用户创建工程项目成功,则在应用程序向导设置的第二步,将询问用户是否需要在项目中支持WindowsSocket功能,如图2.1所示。

图2.1支持WindowsSocket功能,如果用户在应用程序的第二步没有选择项目支持WindowsSocket功能,则在程序中手动添加代码也可以达到同样的目的。

其代码如下:

#include/包含CSocket类的头文件注意:

头文件afxsock.h中包含了CSocket类的变量以及函数定义。

2.2.2Winsock编程流程,在本书的第1章中,已经向用户介绍了Winsock函数是用于网络编程的WindowsAPI函数。

本章在前一节中,向用户介绍了CSocket类的基本编程流程。

所以,在本节中将向用户介绍使用SocketAPI函数进行网络程序开发的基本流程与方法。

1初始化和释放套接字库,由于所有的Winsock函数均是从动态链接库WS2_32.DLL中导出的,但是,VC在默认情况下并没有与该库进行连接。

所以,用户需要在VC中进行相关设置,使其连接动态库WS2_32.DLL。

添加方法是选择“Project”|“Settings”命令,将弹出ProjectSettings对话框,如图2.2所示。

图2.2添加动态链接库,用户在工程设置对话中,可以修改或添加库模块(如图2.2所示)。

在库模块中添加动态链接库WS2_32.DLL。

这样,程序就可以调用Winsock函数了。

用户必须首先从动态链接库中调用函数WSAStartup()对该库进行初始化,之后才能从该库中继续正确调用其他Winsock函数。

否则,将出现错误。

函数WSAStartup()的原型如下:

intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);该函数调用成功,将返回0。

否则,调用函数失败。

参数wVersionRequested表示当前套接字库的版本号。

例如,当前套接字版本号为2.0,则将该参数设置为2.0。

代码如下:

WORDwVersionRequested=MAKEWORD(2,0);,参数lpWSAData指向结构体WSADATA的指针变量,表示获取到的套接字库详细信息。

该结构体定义如下:

typedefstructWSADataWORDwVersion;/库文件建议应用程序使用的版本号WORDwHighVersion;/库文件支持的最高版本charszDescriptionWSADESCRIPTION_LEN+1;/描述库文件的字符串charszSystemStatusWSASYS_STATUS_LEN+1;/系统状态字符串unsignedshortiMaxSockets;/同时支持的最大套接字数unsignedshortiMaxUdpDg;/已废弃charFAR*lpVendorInfo;/已废弃WSADATA,FAR*LPWSADATA;,用户初始化套接字库,代码如下:

WSADatadata;/定义WSAData变量WORDwVersionRequested=MAKEWORD(2,0);/定义套接字库版本号:

WSAStartup(wVersionRequested,2创建套接字句柄,在SocketAPI中,创建套接字句柄的函数是socket()。

该函数原型如下:

SOCKETsocket(intaf,/指定套接字所使用的地址格式,在本章中只能设置为AF_INETinttype,/套接字类型intprotocol/如果参数type已经指定套接字类型为TCP或UDP,则该参数可以设置为0);该函数执行成功,将返回新创建的套接字句柄。

否则,将返回INVALID_SOCKET表示失败。

参数type的取值如表2.1所示。

表2.1套接字类型取值,例如,创建流式套接字的句柄。

代码如下:

SOCKETs;/定义套接字句柄s=:

socket(AF_INET,SOCK_STREAM,0);/创建并返回套接字句柄,3绑定地址信息,对于服务器而言,套接字创建成功后,还应该将套接字与地址结构信息相关联。

实现这一功能的函数是bind()。

该函数原型如下:

intbind(SOCKETs,/套接字句柄conststructsockaddrFAR*name,/地址结构信息intnamelen/地址结构的大小);该函数调用成功,则返回0。

否则,函数调用失败。

例如,将套接字句柄绑定到本地地址,代码如下:

./省略部分代码sockaddr_inaddr;/定义套接字地址结构变量addr.sin_family=AF_INET;/指定地址家族为TCP/IPaddr.sin_port=htons(80);/指定端口号addr.sin_addr.S_un.S_addr=INADDR_ANY/表示服务器能够接收任何计算机发来的请求:

bind(s,(sockaddr)/绑定套接字到指定地址结构,当服务器程序将套接字句柄绑定套接字地址成功时,则调用函数listen()实现监听端口的功能。

该函数原型如下:

intlisten(SOCKETs,/实现监听功能的套接字句柄intbacklog/指定监听的最大连接数量);该函数仅被用于流式套接字上。

如果多个客户端同时向服务器发出连接请求,并且已超过了最大监听数,则客户端将返回错误代码。

例如,程序在已创建的套接字s上进行监听,代码如下:

./省略部分代码:

listen(s,5);/在套接字上进行监听,并且将最大监听数指定为5,4连接,客户端程序连接服务器使用函数connect()实现。

函数原型如下:

intconnect(SOCKETs,/套接字句柄conststructsockaddrFAR*name,/将要连接的服务器地址信息结构指针intnamelen/地址信息结构体长度);,例如,客户端使用该函数连接地址为“127.0.0.1”,端口为80的服务器。

代码如下:

sockaddr_inaddr;/定义套接字地址结构变量addr.sin_family=AF_INET;/指定地址家族为TCP/IPaddr.sin_port=htons(80);/指定端口号addr.sin_addr.S_un.S_addr=inet_addr(127.0.0.1);/指定服务器地址SOCKETs;/定义套接字句柄s=:

socket(AF_INET,SOCK_STREAM,0);/创建并返回套接字句柄:

connect(s,(sockaddr)/连接服务器.,如果服务器接收到客户端的连接请求,则可以调用函数accept()接受该请求。

函数原型如下:

SOCKETaccept(SOCKETs,/套接字句柄structsockaddrFAR*addr,/获取连接对方的地址信息intFAR*addrlen/地址长度);该函数如果调用成功,则返回一个新的套接字句柄,用于通信双方数据的传输。

5数据收发,当用户使用Winsock编程时,都是调用函数send()和recv()进行数据的发送和接收。

函数原型如下:

/发送数据函数intsend(SOCKETs,constcharFAR*buf,intlen,intflags);/接收数据函数intrecv(SOCKETs,charFAR*buf,intlen,intflags);,两个函数的各个参数表示的意义均相同。

参数buf是指向数据缓冲区的指针变量,参数flags通常设置为0。

注意:

如果服务器使用上面的函数进行数据收发,则参数s应该为监听函数返回的新套接字句柄。

如果客户端使用以上函数进行数据收发,则参数s应该为客户端创建的套接字句柄。

6关闭套接字,当套接字使用完毕或程序退出时,用户应该调用函数closesocket()关闭套接字句柄。

函数原型如下:

intclosesocket(SOCKETs/将关闭的套接字句柄);参数s表示即将关闭的套接字句柄。

例如,用户关闭前面创建的套接字句柄s,代码如下:

:

closesocket(s);本节主要向用户讲述了使用Winsock函数进行程序设计的基本流程,并讲解了部分常用函数的用法等知识。

希望用户在实际编程的过程中,能不断地对本节知识进行回顾,加深理解。

2.2.3基于TCP的Sockets编程,在本节中,将编写一个简单的TCP服务器和TCP客户端程序。

这两个实例程序均为控制台程序窗口。

1TCP服务器,首先,在VC中新建一个基于控制台的应用程序工程,并将该工程命名为“TCP服务器”,如图2.3所示。

图2.3新建控制台应用程序,然后,单击“OK”按钮进行应用程序类型的设置。

在本节中,将新建的控制台程序类型指定为一个空工程,如图2.4所示。

图2.4设置空的控制台程序,用户还需要在VC中添加一个空白的C+源文件,名称为TCPSEVER,如图2.5所示。

图2.5新建C+资源文件,用户在新建的C+源文件中进行代码编写。

代码如下:

编译并运行程序,如图2.6所示。

图2.6服务器启动界面,服务器程序启动以后,如果没有客户端向其发送连接请求,则服务器将一直等待直到有客户端程序连接。

2TCP客户端,在VC中创建基于控制台的应用程序,命名为“TCP客户端”。

其方法与TCP服务器的创建过程相同。

所以,在这里不再赘述,请读者复习前面的相关内容。

在新建的C+源文件TCPClient中,用户可以编写客户端的功能代码。

代码如下:

编译并运行程序,如图2.7所示。

图2.7客户端启动界面,如果用户首先打开服务器程序,再打开客户端程序,则服务器会接受客户端的连接请求,而客户端会显示服务器发送的欢迎信息,如图2.8所示。

图2.8打开服务器与客户端,本节向用户讲解了TCP服务器与客户端的通信过程,并编写了实例代码。

用户在学习的过程中,如果对本章实例有兴趣,可以将随书光盘中的相应的实例代码进行改写,以达到自己的要求。

2.2.4基于UDP的Sockets编程,基于UDP的网络程序是面向无连接,不可靠的一种应用程序。

所以,当程序创建套接字句柄成功以后,便可以直接调用函数进行数据收发,最后,关闭套接字对象。

在整个过程中,程序都不用调用任何函数连接服务器或者接受客户端的连接等操作。

这种类型的应用程序多用在即时通信中。

在UDP中进行数据收发的函数是sendto()和recvfrom()。

函数原型如下:

intsendto(/发送函数SOCKETs,/套接字句柄constcharFAR*buf,/数据缓冲区intlen,/数据的长度intflags,/一般设置为0conststructsockaddrFAR*to,/目标地址结构信息inttolen/目标地址结构大小);intrecvfrom(SOCKETs,charFAR*buf,intlen,intflags,structsockaddrFAR*from,intFAR*fromlen);/接收函数,函数recvfrom()的各个参数与函数sendto()的参数基本一致。

参数from是指向地址结构sockaddr_in的指针,表示数据发送方的地址信息。

参数fromlen表示该地址结构的大小。

1UDP服务器,首先,在VC中创建基于控制台程序窗口的应用程序,并命名为“UDP服务器”,如图2.9所示。

图2.9新建UDP服务器,然后,将该工程类型同样指定为空工程。

在新建的工程中新建一个C+源文件,名称为UDPSever,如图2.10所示。

图2.10新建C+源文件,现在用户可以在该源文件中编写UDP服务器的代码。

代码如下:

编译并运行程序,如图2.11所示。

图2.11UDP服务器启动界面,2UDP客户端,在VC中创建UDP客户端程序时,与UDP服务器相同,工程类型均为空工程。

所以,用户只需在C+源文件中编写代码实现UDP客户端。

代码如下:

编译并运行程序,如图2.12所示。

图2.12客户端

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

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2