《VC++深入详解》学习笔记[11]——第14章 网络编程

来源:互联网 发布:好的小说阅读软件 编辑:程序博客网 时间:2024/06/06 07:20
 

第14章 网络编程

Windows Sockets的实现:Windows Sockets是Windows的网络程序设计接口,它是从Berkeley Sockets扩展而来的,以动态链接库的形式提供使用。它与Berkeley Sockets都基于TCP/IP协议,它们中很多函数都是一致的,如果采用双方共有的这些函数编写网络程序,那么这些网络程序将会很容易地移植到其他系统下。

套接字的类型

       ①流式套接字(SOCK_STREAM):提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序接收。流式套接字实际上是基于TCP协议实现的;

       ②数据报式套接字(SOCK_DGRAM):提供无连接服务。数据包以独立包形式发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。数据报式套接字实际上是基于UDP协议实现的。

       ③原始套接字(SOCK_RAW)

 

基于TCP(面向连接)的socket编程流程:

       服务器端:

       ①创建套接字;

       ②将套接字绑定到一个本地地址和端口上;

       ③将套接字设为监听模式,准备接收客户请求;

       ④等待客户请求到来;当请求到来后接受连接请求,返回一个新的对应于此次连接的套接字;

       ⑤用返回的套接字和客户端进行通信;

       ⑥返回,等待另一客户请求;

       ⑦关闭套接字;

       客户端:

       ①创建套接字;

       ②向服务器发出连接请求;

       ③和服务器端进行通信;

       ④关闭套接字;

基于UDP(面向无连接)的socket编程流程:

       服务器端:

       ①创建套接字;

       ②将套接字绑定到一个本地地址和端口上;

       ③等待接收数据

       ④关闭套接字;

       客户端:

       ①创建套接字;

       ②向服务器发送数据;

       ③关闭套接字;

 

代码解析:

基于TCP(面向连接)的socket编程流程:

服务器端:

#include <Winsock2.h>

#include <stdio.h>

void main()

{

       ///加载套接字库

       WORD wVersionRequested;

       WSADATA wsaData;

       int err;

       wVersionRequested = MAKEWORD( 1, 1 );

                            // MAKEWORD(x,y)宏,x、y分别为高低位字节;

       err = WSAStartup( wVersionRequested, &wsaData );

                            // WSAStartup函数用来加载套接字库并进行套接字库的版本协商

       if ( err != 0 ) return;     

       //判断是否我们请求的winsocket版本,如果不是则调用WSACleanup终止winsocket的使用并返回

       if ( LOBYTE( wsaData.wVersion ) != 1 ||HIBYTE( wsaData.wVersion ) != 1 )

       {

              WSACleanup( );

              return;   

       }

      

       ///创建套接字并绑定到本地地址与端口上

       SOCKET sockSrv = socket(AF_INET, //对于TCP/IP协议的套接字,地址族只能是AF_INET

              SOCK_STREAM,  //创建流式套接字

              0);  //零表示自动选择协议

       SOCKADDR_IN addrSrv;   //定义一个地址结构体的变量;SOCKADDR_IN结构体中除了sa_family                                                   //成员以外,其他成员都是按网络字节顺序表示的

       addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

              //用htonl()方法将INADDR_ANY转换为网络字节序;将地址指定为INADDR_ANY将允许套接字向任何分配给本地机器的IP地址发送或接收数据

       addrSrv.sin_family = AF_INET;

       addrSrv.sin_port = htons(22222); //指定端口号;为所编写的网络程序指定端口号时,要使用1024以上的端口号;htons把u_short类型从主机字节序转换为网络字节序

       bind(sockSrv,(SOCKADDR *) &addrSrv,sizeof(SOCKADDR));

              //SOCKADDR大小写是一样的

      

       ///设置监听

       listen(sockSrv,5);

              // listen函数将指定的套接字设置为监听模式,第二个参数是等待连接队列的最大长度

       SOCKADDR_IN addrClient;//用来接收连接实体的地址

       int len = sizeof(SOCKADDR);

       while(1)

       {     SOCKET sockConn = accept(sockSrv, (SOCKADDR *) &addrClient,&len);

                     //返回一个用于当次通信的SOCKET

              char sendBuf[100];

              sprintf (sendBuf,"Welcome %s to \

                     http://blog.csdn.net/teshorse",

                     inet_ntoa(addrClient.sin_addr));

                            // inet_ntoa函数将一个in_addr结构体类型的参数转换成以点分十进制格式表示的IP地址字符串,相反功能的函数为inet_addr;

              send(sockConn,sendBuf,strlen(sendBuf)+1,0);

              char recvBuf[100];

              recv(sockConn,recvBuf,100,0);

              printf("%s\n",recvBuf);

              closesocket(sockConn);

              …

       }

       WSACleanup( );

}

客户端:

void main()

{    

       ///加载套接字库…

 

       ///创建套接字并连接服务器端,无须绑定

       SOCKET sockClient = socket (AF_INET, SOCK_STREAM, 0);

       SOCKADDR_IN addrSrv;

       addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

              //设定服务器端IP地址,"127.0.0.1"是本地回路地址

              //不管本地主机上有没有网卡,都可以用这个IP测试网络

       addrSrv.sin_family = AF_INET;

       addrSrv.sin_port = htons(22222); //端口号要与服务器端保持一致

       connect(sockClient,(SOCKADDR *)&addrSrv,sizeof(SOCKADDR));

 

       ///接收服务器端发送的数据,并且向服务器端发送数据

       char recvBuf[100];

       recv(sockClient,recvBuf,100,0);

       printf("%s \n", recvBuf);

       getchar();

       send(sockClient,"I'm teshorse",strlen("I'm teshorse")+1,0);

 

       ///关闭套接字,释放资源,并且终止对套接字库的使用

       closesocket(sockClient);

       WSACleanup();

}//endof main()

 

基于UDP(面向无连接)的socket编程流程:

服务器端:

#include <Winsock2.h>

#include <stdio.h>

void main()

{    

       ///加载套接字库…

       ///创建套接字并在本地地址与端口绑定

       SOCKET sockSrv = socket (AF_INET,

              SOCK_DGRAM/*数据报套接字*/, 0);

       SOCKADDR_IN addrSrv;

       addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

       addrSrv.sin_family = AF_INET;

       addrSrv.sin_port = htons(6000);

       bind(sockSrv, (SOCKADDR *)&addrSrv,sizeof(SOCKADDR));

       ///接收数据

       SOCKADDR_IN addrClient;

       int len=sizeof(SOCKADDR);

       char recvBuf[100];

       recvfrom(sockSrv,recvBuf,100,0,

              (SOCKADDR*)&addrClient,&len);

       printf("%s\n",recvBuf);

       closesocket(sockSrv);

       WSACleanup();

}

客户端:

       ///加载套接字库…

       ///创建套接字并发送消息

       SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);

       SOCKADDR_IN addrSrv;

       addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

       addrSrv.sin_family = AF_INET;

       addrSrv.sin_port = htons(6000);

       sendto(sockClient,"hello",strlen("hello")+1,0,

              (SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

       closesocket(sockClient);

       WSACleanup();

 

原创粉丝点击