资源描述:
《网络编程(整理完毕)》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
孙新视频中关于网络编程的总结:SOCKET可以在同一区域的网套接字交换数据,也有可能跨区域通信,但是这只是在执行了某种转换进程后才能实现。Socket编程的前提条件:1.连接动态链接库ws2_32.lib2.头文件要求winsock2.h服务器的构建(TCP/IP)1.WSAStartup(赋值MSDN上的模板代码)2.调用SOCKET,得到一个套接字3.初始化一个结构体sockaddr/sockaddr_in,保存服务器端的网络信息4.调用BIND,绑定一个端口,必须要是1024以上的端口号5.调用listen,把服务器设置为监听模式进入一个循环,等待客户端的请求1.调用accpet,接受客户端的请求2.调用send,发送一个消息给客户端3.调用recv,接受客户端发送过来的信息2.2高版本的是WSARecv()/WSASend()。详细使用见MSDN客户端的构建(TCP/IP)1.WSAStartup(赋值MSDN上的模板代码)2.调用SOCKET,得到一个套接字3.初始化一个SOCKADDR/SOCKADDR_IN的结构体,在结构体中设置要连接的服务器的网络信息4.调用connect连接服务器5.使用send/recv(发送/接受)客户端的信息//注意,基于UDP的编程,使用sendto和recvfrom基于UDP的编程1.连接动态链接库ws2_32.lib2.头文件要求winsock2.h服务器的构建(TCP/IP)1.WSAStartup(赋值MSDN上的模板代码)2.调用SOCKET,得到一个套接字3.初始化一个结构体sockaddr/sockaddr_in,保存服务器端的网络信息4.调用BIND,绑定一个端口,必须要是1024以上的端口号。这是因为必须要告诉系统,要在哪个端口接受数据。5.调用recvfrom/sendto接受/发送一个消息到客户端2.2高版本的是WSARecvfrom()/WSASendTo(),详细见MSDN客户端的构建(TCP/IP)1.WSAStartup(赋值MSDN上的模板代码)2.调用SOCKET,得到一个套接字3.初始化一个SOCKADDR/SOCKADDR_IN的结构体,在结构体中设置要连接的服务器的网络信息7 1.使用sendto/recvfrom(发送/接受)客户端的信息最后相同的步骤:1.调用closesocket()2.调用WSACleanup()异步套接字(要用到WINSOKET2,因此不能用MFC提供函数进行套接字的加载和版本协商):相关函数说明:注册要使用异步阻塞的消息WSAAsyncSelect(SOCKETs,HWNDhWnd,unsignedintwMsg,longlEvent)S:需要做异步阻塞的套接字hWnd:接受异步消息的窗口的句柄wMsg(自定义函数请看资料锦集):一个自定义消息。自定义消息需要带两个参数:WPARAMANDLPARAMlEvent:需要做异步处理的消息的一个异或集合。提供了消息机制的网络事件选择,当使用它登记的网络事件发生时,Windows应用程序相应的窗口函数将收到一个消息,消息中指示了发生的网络事件,以及与事件相关的一些信息。原因:ThewParamparameteridentifiesthesocketonwhichanetworkeventhasoccurred.ThelowwordoflParamspecifiesthenetworkeventthathasoccurred.翻译:wParam消息确定了一个已经发生的网络事件,而低字节的lParam这个参数指向了这个已经发生的网络事件。使用函数LOWORD(lParam)。WSAEnumProtocols(LPINTlpiProtocols,LPWSAPROTOCOL_INFOlpProtocolBuffer,ILPDWORDlpdwBufferLength)lpiProtocols:一个以NULL结尾的协议标识号数组。这个参数是可选的,如果lpiProtocols为NULL,则返回所有可用协议的信息,否则,只返回数组中列出的协议信息。lpProtocolBuffer,[out]:一个用WSAPROTOCOL_INFO结构体填充的缓冲区。WSAPROTOCOL_INFO结构体用来存放或得到一个指定协议的完整信息。lpdwBufferLength,[in,out]:在输入时,指定传递给WSAEnumProtocols()函数的lpProtocolBuffer缓冲区的长度;在输出时,存有获取所有请求信息需传递给WSAEnumProtocols()函数的最小缓冲区长度。这个函数不能重复调用,传入的缓冲区必须足够大以便能存放所有的元素。这个规定降低了该函数的复杂度,并且由于一个机器上装载的协议数目往往是很少的,所以并不会产生问题。Win32平台支持多种不同的网络协议,采用Winsock2,就可以编写可直接使用任何一种协议的网络应用程序了。通过WSAEnumProtocols函数可以获得系统中安装的网络协议的相关信息。7 基于socket编程的以上函数的中文解释:intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);wVersionRequested:参数用于指定准备加载的winsock库的版本,高位字节指定所需要的Winsock库的副版本,而低位字节则是主版本,可用MAKEWORD(X,Y)(其中,x是高位字节,y是低位字节)方便低获取wVersionRequested的正确值。lpWSAData:参数是指向WSADATA结构的指针,WSAStartup用其加载的库版本有关的信息填在这个结构中。AfxSocketInit():MFC自动加载套接字库(加载的是1.1的版本。而且由于使用了这个函数,不用手动去设置动态链接库ws2_32.lib)。头文件是:Afxsock.hSOCKETsocket(intaf,inttype,intprotocol);af:对于TCP/IP协议的套接字,他只能是AF_INET(PF_INET)。这是因为Window只支持一个网际域——AF_INET。type:指定Socket类型,对于1.1版本的Socket,它只支持两种类型的套接字,SOCK_STREAM(应用于服务器/客户端模式),SOCK_DGRAM(应用于UDP模式),protocol:与特定的地址家族相关的协议,如果指定为0,那么它就会根据地址格式和套接字类别,自动为你选择一个合适的协议。这是推荐使用的一种选择协议的方法。函数调用成功后,返回一个新的SOCKET数据类型的套接字描述符,如果失败,返回INVALID_SOCKET,错误信息可以用过WSAGetLastError函数返回以下是2.2版本的函数。注意版本的不同。(在WSAStartup()函数中设置,这个函数MSDN有模板)SOCKETWSASocket(intaf,inttype,intprotocol,LPWSAPROTOCOL_INFOlpProtocolInfo,GROUPg,DWORDdwFlags);前三个参数和socket()函数的前三个参数含义一样。LpProtocolInfo:一个指向WSAPROTOCOL_INFO结构体的指针,该结构定义了所创建的套接字的特性。如果lpProtocolInfo为NULL,则WinSock2DLL使用前三个参数来决定使用哪一个服务提供者,它选择能够支持规定的地址族、套接字类型和协议值的第一个传输提供者。如果lpProtocolInfo不为NULL,则套接字绑定到与指定的结构WSAPROTOCOL_INFO相关的提供者。G:保留的。dwFlags:套接字属性的描述。7 intbind(SOCKETs,conststructsockaddrFAR*name,//FAR*表示远指针,是win16的产物,在win32已经淘汰intnamelen);s:指定要绑定的套接字structsockaddr:指定了该套接字的本地地址信息,是指向sockeaddr结构的指针变量,由于该地址结构是为所有的地址家族准备的,这个结构可能(通常会)随所使用的网络协议不同而不同。所以要使用第三个参数指定该地址结构的长度namelen:指定structsockaddr的长度bind中指定的结构体:structsockaddr{u_shortsa_family;charsa_data[14];};sin_family:指定该地址家族,在这里必须设为AF_INETsa_data[14]:表示一个内存去,起到占位的作用,该区域中指定与协议相关的具体地址信息,由于实际要求的只是内存去,所以对于不同的协议家族,用不同的结构体来替换sockaddr。除了sa_family外,sockaddr是按网络字节顺序表示的。在TCP/IP中,我们可以用sockaddr_in结构替换sockaddr,以方便我们填写地址信息。structsockaddr_in{shortsin_family;u_shortsin_port;structsin_port;sin_addr;charsin_zero[8];};sin_family:表示地址族,对于IP地址,sin_family成员讲一直是AF_INETsin_port:将要分配的套接字的端口(必须是指定1024以上的端口号)sin_addr:套接字的主机的IP地址将IP地址指定为INADDR_ANY,允许套接字向任何分配给本地机器的IP地址发送或者接受数据,多数情况下,每个机器只有一个IP地址,但有的机器可能会有多个网卡,每个网卡都可以用自己的IP地址,使用INADDR_ANY可以简化应用程序的编写,将地址指定为INADDR_ANY,允许一个独立应用接受发自多个接口的回应。如果我们指向让套接字使用多个IP中的一个地址,就必须指定实际地址,要做到这一点,可以用inet_addr()函数,这个函数需要一个字符串作为其参数,该字符串指定了以点分十进制格式表示的IP地址(如:192.168.1.1)。而inet_addr()函数会返回一个适合分配给S_addr的u_long类型的数值。inet_ntoa()函数会完成相反的转换。他接受一个in_addr结构体类型的参数,并返回一个以点分十进制格式表示的IP地址字符串sin_zero:只是一个填充数,以使sockaddr_in和sockaddr结构的长度一样。如果这个函数调用成功,它将返回0,如果调用失败,这个函数就会返回一个SOCKET_ERROR,错误信息可以用过WSAGetLastError函数返回structin_addr{union{struct{u_chars_b1,s_b2,s_b3,s_b4;}S_un_b;struct{u_shorts_w1,s_w2;}S_un_w;u_longS_addr;}S_un;第三个参数的结构体,是一个共用体:7 intlisten(SOCKETs,intbacklog);s:套接字bakclog:最大连接数SOCKETaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);s:套接字(处于监听的套接字)sockadrr:接受客户端的网络信息(这个结构体必须与bind中的结构体是同一类(示例代码用得是sockaddr_in))addrlen:第二个参数结构体的长度(使用sizeof函数求得)返回的是请求连接的客户端的套接字信息。intsend(SOCKETs,constcharFAR*buf,intlen,intflags);s:套接字(accept返回的套接字,处于非监听的)buf:要发送的内容len:发送内容的长度(比要发送内容的长度多1,可以使接收端增加结束符)flags:可以设置为0,具体作用可以见MSDNintWSASendTo(SOCKETs,LPWSABUFlpBuffers,DWORDdwBufferCount,LPDWORDlpNumberOfBytesSent,DWORDdwFlags,conststructsockaddrFAR*lpTo,intiToLen,LPWSAOVERLAPPEDlpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINElpCompletionRoutine);S:标识一个套接字(可能已连接)的描述符。lpBuffers:一个指向WSABUF结构体的指针。每一个WSABUF结构体包含一个缓冲区的指针和缓冲区的长度。dwBufferCount,lpBuffers:数组中WSABUF结构体的数目。lpNumberOfBytesSent,[out]:如果发送操作立即完成,则为一个指向本次调用所发送的字节数的指针。dwFlags:指示影响操作行为的标志位。lpTo:可选指针,指向目标套接字的地址。iToLen:lpTo中地址的长度。lpOverlapped:一个指向WSAOVERLAPPED结构的指针(对于非重叠套接字则忽略)。7 lpCompletionRoutine:一个指向接收操作完成时调用的完成例程的指针(对于非重叠套接字则忽略)。intrecv(SOCKETs,charFAR*buf,intlen,intflags);s:套接字(accept返回的套接字)buf:接受到的数据len:接受到数据的长度flags:可以设置为0,具体作用可以见MSDNUDP接收函数intrecvfrom(SOCKETs,charFAR*buf,intlen,intflags,structsockaddrFAR*from,intFAR*fromlen);以下是2.2版本接受函数intWSARecvFrom(SOCKETs,LPWSABUFlpBuffers,DWORDdwBufferCount,LPDWORDlpNumberOfBytesRecvd,LPDWORDlpFlags,structsockaddrFAR*lpFrom,LPINTlpFromlen,LPWSAOVERLAPPEDlpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINElpCompletionRoutine);S:标识套接字的描述符。lpBuffers:[in,out]:一个指向WSABUF结构体的指针。每一个WSABUF结构体包含一个缓冲区的指针和缓冲区的长度。dwBufferCount,lpBuffers:数组中WSABUF结构体的数目。lpNumberOfBytesRecvd,[out]:如果接收操作立即完成,则为一个指向本次调用所接收的字节数的指针。lpFlags,[in,out]:一个指向标志位的指针。lpFrom,[out]:可选指针,指向重叠操作完成后存放源地址的缓冲区。lpFromlen,[in,out]:指向from缓冲区大小的指针,仅当指定了lpFrom才需要。lpOverlapped:一个指向WSAOVERLAPPED结构体的指针(对于非重叠套接字则忽略)。lpCompletionRoutine:一个指向接收操作完成时调用的完成例程的指针(对于非重叠套接字则忽略)。intconnect(7 SOCKETs,conststructsockaddrFAR*name,intnamelen);s:套接字structsockaddr:设置连接服务器的地址信息(注意:可以用SCOKADDR_IN代替,必须要与服务器端的这个结构体相同)初始化结构体中的sin_port的端口应该与服务器设置的端口一样。namelen:结构体的长度网络编程中的转换函数网络字节序与主机字节序的转换:1.htons把unsignedshort类型从主机序转换到网络序2.htonl把unsignedlong(u_long)类型从主机序转换到网络序3.ntohs把unsignedshort类型从网络序转换到主机序4.ntohl把unsignedlong类型从网络序转换到主机序转换成S_addr地址:(转换成点分十进制或者是一个字符串)1.inet_addr(constchar*cp)//点分十进制转换成IP字符串2.charFAR*inet_ntoa(structin_addrin)//IP字符串转换成点分十进制7