C++ socket 通信客戶端和服務器端

#include <iostream>  
#include <stdio.h>  
#include <windows.h> //一定要包含該頭文件
#pragma comment(lib, "WS2_32.lib")  //windwows下的socket編程函數庫
using namespace std;     
int main()  
{  
  WSADATA wsaData; 
  WORD sockVersion = MAKEWORD(2, 2);  
  //windows網絡編程庫的版本號信息
  SOCKET sock = 0;  //TCP通信的socket數據結構 
  if (WSAStartup(sockVersion, &wsaData) != 0)  
  //WSAStartup函數是在程序中初始化並加載Windows網絡
  {  
     cout << "initlization failed!" << endl;  
     exit(0);  
     //如果WSAStartup返回值爲1的話就表示ws2_32.dll文件有問題,程序退出
  }  

  sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  //在本機上創建一個socket  
  if (sock == INVALID_SOCKET)  //判斷socket是否創建成功
  {  
    cout << "failed socket!" << endl;  
    return 0;  //如果創建失敗就在程序中返回0結束程序
  }  

  sockaddr_in sin;  
  //創建一個socket編程類型的網絡地址數據結構以便connect函數對本機創建的socket數據
  //結構進行初始化。
  sin.sin_family = AF_INET;   //設置網絡協議族類型
  sin.sin_port = htons(4567);  //設置遠程計算機的端口號
  sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//設置遠程計算機的IP地址 
  if (connect(sock, (sockaddr*)&sin, sizeof(sockaddr)) == -1) 
  //初始化socket並連接遠程計算機
  {  
      cout << "connect failed!" << endl;  
      return 0;  //連接失敗就返回0到程序
  }   
  char buffer[256] = "\0";  //聲明一個從網絡接收數據的緩存區
  int  nRecv = 0;  //聲明一個從網絡接收到的數據字節長度   
  nRecv = recv(sock, buffer, 256, 0);  
  //recv是一個接收網絡的TCP數據包函數,nRecv是從網絡接收到數
  //據的字節長度 
  if (nRecv > 0)  
  {  
      buffer[nRecv] = '\0';  
      //如果接收到網絡數據包長度大於0的話就在接收到的數據包未尾添加一個字符串
      //結束符  
      cout << "reveive data: " << buffer << endl;
      //按字符串格式輸出接收到的數據 
  }  
  closesocket(sock);  //關閉這個TCP網絡通信連接
  WSACleanup();  //釋放ws2_32.dll動態庫
 }  

  //服務端:  
  #include <iostream>  
  #include <stdio.h>  
  #include <windows.h>  //一定要包含該頭文件

  using namespace std;    
  #pragma comment(lib, "WS2_32.lib") 
  //windwows下的socket編程函數庫
  int main()  
  {  
      WSADATA wsaData;  
      WORD sockVersion = MAKEWORD(2, 2); 
      //windows網絡編程庫的版本號信息
      SOCKET sListen = 0;  //TCP通信的socket數據結構
      sockaddr_in sin  = {0};  
      //創建一個socket編程類型的網絡地址數據結構這個用於本地
      sockaddr_in remoteAddr = {0};
      //創建一個socket編程類型的網絡地址數據結構這個用於儲存遠程主機的
      //IP地址和端口號 
      char szText[] = "TCP Server Demo";  
      int nAddrLen = 0;  
      nAddrLen = sizeof(sockaddr_in);  
      //計算這個sockaddr_in數據結構的大小
      sin.sin_port = htons(4567);  
      //設置本地(這裏指服務端)計算機要打開的端口
      sin.sin_family = AF_INET;  //設置網絡通信的網絡協議族類型
      sin.sin_addr.S_un.S_addr = INADDR_ANY; 
      //設置本地計算機的IP地址,一般INADDR_ANY在程序運行時
      //會自動計算成本地的IP地址的
      //init wsa  
      if (WSAStartup(sockVersion, &wsaData) != 0)
      //WSAStartup函數是在程序中初始化並加載Windows網絡
      {  
          cout << "initlization failed!" << endl;  
          exit(0);  
          //如果WSAStartup返回值爲1的話就表示ws2_32.dll文件有問題,程序退出
     }  

     sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
     //在本機上創建一個socket
     //使用bind函數綁定本機的ip和打開端口到本機創建的socket結構上,並初始化該socket
     //重點說明一個在服務器上是用bind函數來初始化socket,在客戶機上是用connect函數來初始化socket的喔
    if (bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)  
     {  
         cout << "bind failed!" << endl;  
         return 0;  //如果socket綁定失敗返回程序0並退出程序
     }    
    if (listen(sListen, 2) == SOCKET_ERROR) 
    //listen是用來打開本地計算機的端口,參數2表示客戶端同
    //時連接服務器的數量,這裏是說可以同時有2個客戶端連接
    //到本機打開的端口
    {  
           cout << "listen failed!" << endl;   
           return 0;  
           //如果打開本地端口失敗就返回0並退出程序 
    }  

    SOCKET sClient = INADDR_ANY;  
    //再服務器上再創建一個socket結構,用來儲存與一個客戶端進行通信連
    //接的連接實例   
    while (true)  
    {  
      //accept函數是用來創建一個TCP通信連接實例的,他使用一個遠程計算機的IP地址和本地計算機上創建的一個
      //socket,這兩個信息來創建一個本地計算機到遠程計算機的一個TCP通信連接實例的socket,sClient就是當前
      //程序中的這個連接實例的socket 了。注accept函數也可以直接理解爲接受一個客戶機的連接請求。     
    sClient = accept(sListen, (SOCKADDR*)&remoteAddr, &nAddrLen);  
    if (sClient == INVALID_SOCKET)  
    {  
       cout << "accept failed!" << endl;  
       continue;  
       //如果本地計算機(服務器)接受一個客戶端連接請求失敗就退出監聽狀態
     }  
  //send函數是在TCP連接建立之後,就來發送數據的。其中sClient是存放有一個連接實例的socket結構來
  //的。這個服務器上的send函數的socket參數和客戶機上的socket參數是不同的喔,記住這裏的socket參數是通過
  //accept函數創建的喔。不是用connet函數和bind函數創建喔。一定要記住這個sClient是一個關鍵來的。然後
  //szText就是我們想要發送的數據了。這裏我們向連接到該服務器的客戶端發送了一個“TCP Server Demo”的信息。
   send(sClient, szText, strlen(szText), 0);  
   closesocket(sClient);   
   //關閉這個用accept函數建立socket對象,關閉與remoteAddr連接通信。
   //remoteAddr這結構理包含了有遠程計算機的IP和端口號信息,當客戶機
   //使用connect函數發送一個連接請求時,被accept函數接受並處理後,遠
   //程計算機的IP地址和端口信息就被填到了remoteAddr這個結構中去

  }  
  closesocket(sListen);  
  //關閉本地計算機(服務器)上的由bind函數創建的socket對象,關閉本機
  //打開的端口,關閉服務器  
  WSACleanup();  
  //釋放ws2_32.dll動態庫
  }   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章