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");          //用於防止閃退
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章