MFC——10.网络编程基础

Lesson10:网络编程基础

 

网络编程是计算机编程的一个重要分支,是网络通信的基础,网络编程主要用到了Windows系统系统提供的socket。网络通信又分为基于TCP和基于UDP两种。本文主要讲解基于TCP和UDP的网络编程基础知识。

1.      基于TCP的socket编程


1.1  TCP服务器

#include <winsock2.h>
#include <stdio.h>
//#include <iostream>
#pragma comment(lib,"ws2_32.lib")       //静态加入一个lib文件,也就是库文件ws2_32.lib文件,它提供了对以下网络相关API的支持
void main()
{
         /********            首先设定通信版本        **************/
         WORDwVersionRequested;
         WSADATAwsaData;
         interr;
 
         wVersionRequested= MAKEWORD(1, 1);     //请求的通信版本为(1,1)
 
         err= WSAStartup(wVersionRequested, &wsaData);      //调用WSAStartup函数
         if(err != 0)
                   return;     //如果返回值不为0,表示没有对应的WinSockDLL.则返回
 
         if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
         {
                   WSACleanup();     //如果版本的高字节不为1,低字节不为1,则返回。                
                   return;
         }
 
         //1创建套接字
         SOCKETsockSrv = socket(AF_INET, SOCK_STREAM,0);           //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议)     调用成功返回新的socket数据类型的套接字描述符
        
         //2绑定套接字到本地地址和端口
 
         /*structsockaddr_in{
                   short            sin_family;         //地址族
                   unsignedshort      sin_port;        //端口号
                   struct   in_addr     sin_addr;      //套接字的主机IP地址
                   char   sin_zero[8];      //填充数,使sockaddr_in和sockaddr结构长度一样
         }*/
 
         SOCKADDR_INaddrSrv;
         addrSrv.sin_addr.S_un.S_addr= htonl(INADDR_ANY);          //调用htonl函数进行转换主机字节序为TCP/IP网络字节序//addrSrv是一个结构体,里面有一个结构体变量sin_addr,里面包含共用体S_un,然后是共用体成员S_addr,inet_addr函数进行主机字节序转换为网络字节序
         addrSrv.sin_family= AF_INET;
         addrSrv.sin_port=htons(6000);             //端口号为6000,需要1024以上端口号,网络字节序,需要转换,htonl和htons不同在于转换数据的范围
  
       bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));        //绑定套接字和地址的  函数   (1指定要绑定的套接字,2该套接字的本地地址信息,是指向sockaddr结构的指针变量,3指定该地址的长度)
 
         //3调用listen函数,将套接字设置为监听模式,准备接受客户请求
         listen(sockSrv,5);       //(套接字描述符,最大的等待连接队列数)
        
         //4等待客户请求到来
         //5用返回的套接字和客户端进行通信
         //6返回,等待另一个客户请求
         //7关闭套接字
        
         SOCKADDR_INaddrClient;     //定义一个地址结构的变量,用来接受客户端的地址信息,在循环结构中用到
         intlen = sizeof(SOCKADDR);
         while(1)              //死循环,一直监听,持续运行
         {  
                   SOCKETsockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);            //(1处于监听状态的主机服务器套接字描述符,2指向buffer指针连接实体地址,保存了发起客户端的ip信息和端口信息,3指向整型指针,包含返回地址结构的长度),返回一个新的连接的套接字描述符,用他和客户端通信,先前的套接字继续监听客户连接请求
                  
                   //发送数据
                   /*intsend(
                            SOCKETs,      //建立连接所对应的套接字描述符,不是监听的套接字
                            constchar FAR * buf,      //一个buff指针,包含将要传送的数据
                            int len,                 //buffer中数据的长度
                            intflags                //设定send的调用行为
                            );*/
 
                   charsendBuf[100];
                   sprintf_s(sendBuf,"Welcome%s to http://www.sunxin.org",inet_ntoa(addrClient.sin_addr));    //把格式化的数据写入某个字符串,将客户端地址传给字符串里的%s,
                   send(sockConn,sendBuf, strlen(sendBuf)+1, 0);
 
                   //接受数据
                   /*intrecv(             The Windows Socketsrecv function receives data from a connected socket.
                            SOCKETs,               //建立连接的套接字
                            charFAR* buf,           //接受数据的buff
                            intlen,                 //buff的长度
                            intflags                //设定接受函数的调用行为
                            );*/
 
                   charrecvBuf[100];
                   recv(sockConn,recvBuf, strlen(recvBuf) + 1, 0);
                   printf("%s\n",recvBuf);
                   closesocket(sockConn);
         }
}

1.2  TCP客户端

#include <winsock2.h>
#include <stdio.h>
//#include <iostream>
#pragma comment(lib,"ws2_32.lib")
void main()
{
         /********            首先设定通信版本        **************/
         WORDwVersionRequested;
         WSADATAwsaData;
         interr;
 
         wVersionRequested= MAKEWORD(1, 1);      //请求的通信版本为(1,1)
 
         err= WSAStartup(wVersionRequested, &wsaData);  //调用WSAStartup函数
         if(err != 0)
                   return;            //如果返回值不为0,表示没有对应的WinSockDLL.则返回
 
         if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
         {
                   WSACleanup();     //如果版本的高字节不为1,低字节不为1,则返回。                
                   return;
         }
 
         //1创建套接字
         SOCKETsockClient= socket(AF_INET, SOCK_STREAM, 0);           //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议)     调用成功返回新的socket数据类型的套接字描述符
 
         /*intconnect(         //The Windows Socketsconnect function establishes a connection to a specifed socket.
                   SOCKETs,                                //套接字
                   conststruct sockaddr FAR*  name,        //地址结构体指针,用来设定链接的服务器地址信息
                   intnamelen                              //地址结构体的长度
                   );*/
         //2连接服务器
         SOCKADDR_INaddrSrv;                           //SOCKADDR_IN是一个结构体变量
         addrSrv.sin_addr.S_un.S_addr= inet_addr("127.0.0.1");       //addrSrv是一个结构体,里面有一个结构体变量sin_addr,里面包含共用体S_un,然后是共用体成员S_addr,inet_addr函数进行主机字节序转换为网络字节序
         addrSrv.sin_family= AF_INET;
         addrSrv.sin_port= htons(6000);    //主机字节序转换为网络字节序
 
         connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
 
         //3和服务器端口进行通信(接受服务器发送的信息)
         charrecvBuf[100];
         recv(sockClient,recvBuf, strlen(recvBuf) + 1, 0);
         printf("%s\n",recvBuf);
         send(sockClient,"This is zhangsan", strlen("This is zhangsan") + 1, 0);
 
         //4关闭套接字
         closesocket(sockClient);
         WSACleanup();                //终止对套接字库的使用
         system("pause");             //用于防止闪退
}

2.      基于UDP的socket编程

2.1   UDP服务器

#include <winsock2.h>
#include <stdio.h>
 
#pragma comment(lib,"ws2_32.lib")
 
void main()
{
         /********            首先设定通信版本        **************/
         WORDwVersionRequested;
         WSADATAwsaData;
         interr;
 
         wVersionRequested= MAKEWORD(1, 1);            //请求的通信版本为(1,1)
 
         err= WSAStartup(wVersionRequested, &wsaData);      //调用WSAStartup函数
         if(err != 0)
                   return;        //如果返回值不为0,表示没有对应的WinSockDLL.则返回
 
         if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
         {
                   WSACleanup();      //如果版本的高字节不为1,低字节不为1,则返回。                
                   return;
         }
 
         //1创建套接字
         SOCKETsockSrv = socket(AF_INET, SOCK_DGRAM, 0);      //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议)     调用成功返回新的socket数据类型的套接字描述符
 
         //2绑定套接字到本地地址和端口
         SOCKADDR_INaddrSrv;
         addrSrv.sin_addr.S_un.S_addr= htonl(INADDR_ANY);       //调用htonl函数进行转换主机字节序为TCP/IP网络字节序
         addrSrv.sin_family= AF_INET;
         addrSrv.sin_port= htons(6000);              //端口号为6000,1024以上端口号,需要网络字节序,需要转换,htonl和htons不同在于转换数据的范围
 
         bind(sockSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR));     //绑定函数   (1指定要绑定的套接字,2该套接字的本地地址信息,是指向sockaddr结构的指针变量,3指定该地址的长度)
 
         /*intrecvfrom(             The Windows Socketsrecvfrom function receives a datagram and stores the source address.
                   SOCKETs,             //套接字
                   charFAR* buf,        //接收数据的buffer
                  int len,              //buffer的长度
                  int flags,            //设定recvfrom函数的调用行为
         structsockaddr FAR* from,      //地址结构体指针,接收发送数据方的地址信息
                   intFAR* fromlen      //函数返回值,返回地址结构的大小
                   );*/
 
         //3等待接收数据recvfrom
 
         SOCKADDR_INaddrClient;     //定义一个地址结构的变量,用来接受客户端的地址信息,在循环结构中用到
         intlen = sizeof(SOCKADDR);
         charrecvBuf[100];
 
         recvfrom(sockSrv,recvBuf, strlen(recvBuf) + 1, 0, (SOCKADDR*)&addrClient, &len);
         printf("%s\n",recvBuf);
 
         //4关闭套接字
         closesocket(sockSrv);
         WSACleanup();                     //终止对套接字库的使用
         system("pause");                   //用于防止闪退
}

2.2   UDP客户端

#include <winsock2.h>
#include <stdio.h>
 
#pragma comment(lib,"ws2_32.lib")
 
void main()
{
         /********            首先设定通信版本        **************/
         WORDwVersionRequested;
         WSADATAwsaData;
         interr;
 
         wVersionRequested= MAKEWORD(1, 1);         //请求的通信版本为(1,1)
 
         err= WSAStartup(wVersionRequested, &wsaData);    //调用WSAStartup函数
         if(err != 0)
                   return;          //如果返回值不为0,表示没有对应的WinSockDLL.则返回
 
         if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
         {
                   WSACleanup();     //如果版本的高字节不为1,低字节不为1,则返回。                
                   return;
         }
 
         //1创建套接字
         SOCKETsockClient = socket(AF_INET, SOCK_DGRAM, 0);           //(1地址族AF_INET 或 PF_INET,2socket类型SOCK_STREAM或 SOCK_DGRAM,3与特定的地址家族相关的协议)     调用成功返回新的socket数据类型的套接字描述符
 
         /*intsendto(   The Windows Sockets sendtofunction sends data to a specific destination.
                   SOCKETs,                    //套接字
                   constchar FAR * buf,        //包含将要发送的数据
                  int len,                     //数据的长度
                   intflags,                   //设置sendto函数调用行为
                   conststruct sockaddr FAR * to,   //地址结构体指针,设定目的套接字的地址信息
                   inttolen                         //地址结构体的长度
                   );*/
 
         //2向服务器发送数据(sendto)
         SOCKADDR_INaddrSrv;
         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));
 
         //3关闭套接字
         closesocket(sockClient);
         WSACleanup();           //终止对套接字库的使用
         system("pause");          //用于防止闪退
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值