您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > Winsock-TCP编程基础
TCP/IP网络编程项目化教程唐四薪清华大学出版社3.2Winsock开发组件和运行组件VC++新增的数据类型数据类型对应的基本数据类型说明BSTRunsignedshort*16位字符指针DWORDunsignedlong32位无符号整数,段地址和相关的偏移地址LPARAMunsignedint作为参数传递给窗口过程或回调函数的32位值LPCSTRconstchar*指向字符串常量的32位指针LPSTRchar*指向字符串的32位指针LPVOIDvoid*指向未定义的类型的32位指针UNITunsignedint32位无符号整数WORDunsignedshort16位无符号整数WPARAMunsignedint作为参数传递给窗口过程或回调函数的32位值LP表示指针WinSock的头文件和链接库文件版本头文件静态链接库文件动态链接库文件WinSock1winsock.hwinsock.libwinsock.dllWinSock2winsock2.hws2_32.libws2_32.dllVisualC++使用WinSock的步骤1.包含WinSock头文件:#includewinsock2.h2.链接WinSock导入库,有两种方式:在VC6.0的“工程→设置”菜单中,选择“连接”选项卡,在对话框中的“对象/库模块”下输入“Ws2_32.lib”。在程序中使用预处理命令“#pragmacomment”:#pragmacomment(lib,Ws2_32.lib)3.加载WinSock动态链接库:。使用WSAStartup()函数,函数原型如下:intWSAStartup(WORDwVersionRequested,//版本号LPWSADATAlpWSAData//结构体的指针);sockaddr_in结构体sockaddr_in结构用于设置IP和端口structsockaddr_in{shortsin_family;//地址族,IP协议地址对应的值为AF_INETu_shortsin_port;//16位端口号,需使用网络字节顺序structin_addrsin_addr;//32位IP地址,需使用网络字节顺序charsin_zero[8];//保留不用}sockaddr结构体sockaddr结构用于绑定IP和端口structsockaddr{u_shortsa_family;//协议地址族charsa_data[14];//协议地址}该结构为通用套接字地址结构。sockaddr结构的设计就是为了兼容多个不同协议族的地址。观察一下sockaddr_in结构,可以发现这两个结构存储的内容完全一致,因此实际为sockaddr结构的变量赋值时可利用C/C++的强制类型转换进行。sockaddr_inaddrSer;(sockaddr*)&addrSer//强制类型转换或者(LPSOCKADDR)&addrSerunsignedlonginet_addr(char*address)address是以NULL结尾的点分IPv4字符串。该函数返回32位的地址,如果cp字符串包含的不是合法的IP地址,则函数返回。例:in_addraddr;addr.s_addr=inet_addr(202.117.50.26);char*inet_ntoa(structin_addraddress)address是IPv4地址结构,函数返回一指向包含点分IP地址的静态存储区字符指针,如果错误则函数返回NULL地址转换函数inet_addr()字节序转换函数把给定系统所采用的字节序称为主机字节序。为了避免不同类别主机之间在数据交换时由于对于字节序解释的不同而导致的差错,引入了网络字节序。主机到网络u_shorthtons(u_shortshort);u_longhtonl(u_longhostlong);网络到主机u_shortntohs(u_shortshort);u_longntohl(u_longhostlong);第4章TCP通信程序设计4.1简单的TCP程序设计TCP是一个面向连接的传输层协议,提供高可靠性的字节流传输服务,主要用于一次传输要交换大量报文的情形。为了维护传输的可靠性,TCP增加了许多开销:例如确认、流量控制、计时器以及连接管理等。Winsock是通过流式套接字(SOCK_STREAM)来提供TCP服务的。TCPSockets编程创建一个被动模式(server,服务器)的socket.Client/Server交互在发送和接收数据之前client必须调用connect连接服务器server必须调用accept接收client的连接发送和接收数据.关闭连接.TCPSockets编程基本流程socket()bind()listen()accept()send()recv()closesocketsend()socket()recv()closesocketconnect()recv()建立连接数据请求数据响应断连指示ClientServer注意服务器端需要创建两个套接字(监听套接字和通信套接字),客户端只要一个套接字(通信套接字)服务器由socket()创建的套接字是监听套接字,并不用于数据收发。用于收发数据的套接字由accept()函数接收连接请求时创建。客户端由socket()创建的套接字则有两方面用途,一是向服务器发送连接建立请求,二是用于进行客户端的数据收发。1.创建套接字——socket()函数SOCKETsocket(intaf,inttype,intprotocol);监听套接字=socket(AF_INET,套接字的类型,0)相关套接字函数的使用方法2.绑定地址——bind函数socket()函数在创建套接字时并没有为套接字分配地址,需要调用bind函数为其指定本机地址和端口号。intbind(SOCKETs,structsockaddr*name,intnamelen);bind(监听套接字,本地地址,地址长度)注意:客户端可不绑定IP地址客户端的套接字可以不用绑定地址,当客户端程序调用connect()函数与服务器建立连接时,系统会为套接字自动选择一个IP地址和临时端口号。服务器端也可不绑定地址,但由于临时端口号很难被客户知晓从而导致客户无法访问服务器,因此服务器端必须绑定指定的地址。3.开始监听——listen()函数listen()函数是只能由服务器端使用的函数,而且只适用于流式套接字,listen()函数用于将套接字置为监听模式。intlisten(SOCKETs,intbacklog);listen(监听套接字,等待连接的最大个数)4.接受连接——accpet()函数SOCKETaccept(SOCKETs,structsockaddr*addr,intFAR*addrlen);用于接受客户端的连接请求。通信套接字=accept(监听套接字,对方地址,地址长度的指针)5.客户端发送连接请求——connect()函数intconnect(SOCKETs,conststructsockaddr*name,intnamelen);connect(通信套接字,对方地址,地址长度)connect()函数6.send()函数-发送数据intsend(SOCKETs,constchar*buf,intlen,intflags);用于在已经建立连接的套接字上发送数据。send(通信套接字,发送缓冲区,发送数据的长度,0)intrecv(SOCKETs,char*buf,intlen,intflags);用于从连接的套接字中返回数据。该函数执行成功返回实际从套接字s读入到buf中的字节数。7.recv()函数——接收数据recv(通信套接字,接收缓冲区,接收缓冲区的长度,0)总结bind、accept、connect三个函数的参数具有相似性bind(监听套接字,本地地址,地址长度)通信套接字=accept(监听套接字,对方地址,地址长度的指针)connect(通信套接字,对方地址,地址长度)send和recv两个函数send和recv两个函数的参数具有相似性send(通信套接字,发送缓冲区,发送数据的长度,0)recv(通信套接字,接收缓冲区,接收缓冲区的长度,0)套接字的参数总结监听套接字=socket(AF_INET,套接字的类型,0)listen(监听套接字,等待连接的最大个数)closesocket(套接字)TCP服务器端程序流程监听套接字=socket(AF_INET,套接字的类型,0)bind(监听套接字,本地地址,地址长度)listen(监听套接字,等待连接的最大个数)通信套接字=accept(监听套接字,对方地址,地址长度的指针)while(1){recv(通信套接字,接收缓冲区,接收缓冲区的长度,0)send(通信套接字,发送缓冲区,发送数据的长度,0)}closesocket(套接字)TCP客户端程序流程通信套接字=socket(AF_INET,套接字的类型,0)connect(通信套接字,对方地址,地址长度)while(1){send(通信套接字,发送缓冲区,发送数据的长度,0)recv(通信套接字,接收缓冲区,接收缓冲区的长度,0)}closesocket(套接字)注意用closesocket()关闭套接字将导致TCP连接断开,而TCP断开连接采用四次握手机制,也会向对方发送数据包(但这种数据包只有包头,内容为空),这时会触发对方recv()函数的执行。WinSock中的函数都是全局函数,因此也可在这些函数前加“::”,例如::bind()、::listen()、::accept()等,因为“::”运算符左边是类名,如果不属于任何类,则“::”左边为空。4.3数据发送和接收的过程缓冲区是指内存中用于临时存放数据的一片连续的存储空间。使用send()函数发送数据时,应用程序必须事先申请一块内存空间作为缓冲区,并将要发送的数据存放该缓冲区中,这个缓冲区称之为应用程序发送缓冲区charsendbuf[256],recvbuf[256];除了应用程序中的发送缓冲区和接收缓冲区外,每一个套接字也都有自己的发送缓冲区和接收缓冲区。recv()send()应用程序发送缓冲区接收缓冲区应用程序发送缓冲区接收缓冲区发送缓冲区接收缓冲区发送缓冲区接收缓冲区套接字TCP/IP协议栈send()recv()TCP/IP协议栈套接字套接字的缓冲区send()函数所做的工作仅仅是将要发送的数据从应用程序缓冲区中复制到套接字的发送缓冲区;recv()函数接收数据时,其所做的工作也仅仅是将套接字的接收缓存中的数据复制到应用程序接收缓存中。实际的数据发送和接收工作都是由下层的TCP/IP协议自动完成的。
本文标题:Winsock-TCP编程基础
链接地址:https://www.777doc.com/doc-7517344 .html