最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Windows下VScode實現(xiàn)簡單回聲服務(wù)的方法

 更新時間:2021年08月13日 16:54:16   作者:star_function  
回聲服務(wù)端可以將客戶端傳來的信息,再原封不動地發(fā)送給客戶端,因而得名 epoch 服務(wù)。接下來通過本文給大家介紹Windows下VScode實現(xiàn)簡單回聲服務(wù)的方法,感興趣的朋友一起看看吧

1. 相關(guān)知識

1.1 什么是回聲服務(wù)

回聲服務(wù)端可以將客戶端傳來的信息,再原封不動地發(fā)送給客戶端,因而得名 epoch 服務(wù)。服務(wù)端 server 和 客戶端 client 基于 TCP 進(jìn)行通信。

1.2 服務(wù)端、客戶端如何交互

下圖給出了基于 TCP 的服務(wù)器端和客戶端的交互過程。
首先服務(wù)端創(chuàng)建 socket 套接字,之后調(diào)用 bind 函數(shù)分配服務(wù)端 socket 地址,調(diào)用 listen 函數(shù)使服務(wù)端進(jìn)入監(jiān)聽狀態(tài),同時維護(hù)一個半連接隊列。服務(wù)端之后會調(diào)用 accept 函數(shù),進(jìn)入阻塞狀態(tài)。accept 函數(shù)會從全連接的隊列中取出一個連接進(jìn)行處理。TCP 連接建立完成之后,服務(wù)端和客戶端即可通過 send 和 recv 發(fā)送和接收數(shù)據(jù)。
注意:服務(wù)端調(diào)用 listen 函數(shù)進(jìn)入等待連接狀態(tài)后,客戶端才能調(diào)用 connect 函數(shù)發(fā)起連接請求。

在這里插入圖片描述

服務(wù)端和客戶端交互就是一種通信過程,它們基于 TCP 實現(xiàn) socket 通信。TCP 協(xié)議中有三次握手、四次揮手的協(xié)議內(nèi)容,如下圖所示。

在這里插入圖片描述

服務(wù)端和客戶端通過三次握手建立連接,四次揮手?jǐn)嚅_連接。
具體到socket編程實現(xiàn),則是通過 listen 和 connect 函數(shù)實現(xiàn) TCP 連接的建立,通過 close 函數(shù)關(guān)閉 socket 套接字,實現(xiàn)TCP連接的斷開。

2. socket 編程

下面分別介紹客戶端和服務(wù)端的常用函數(shù)和具體實現(xiàn)過程。

2.1 服務(wù)端

服務(wù)端的實現(xiàn)過程如下圖所示。

在這里插入圖片描述

下面給出實現(xiàn)基于TCP的服務(wù)端的常用函數(shù)。

1.首先需要對 Winsock 套接字庫進(jìn)行初始化,調(diào)用 WSAStartup 函數(shù)。
下面給出 WSAStartup 函數(shù)調(diào)用的基本格式,一般只需調(diào)用即可,無需了解參數(shù)含義。

#include <winsock2.h>
int main(int argc, char* argv[])
{
	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
	ErrorHandling("WSAStartup() error!"); 
	return 0;
}

成功時返回 0 ,失敗返回非零的錯誤代碼值。

2.創(chuàng)建 socket 套接字

SOCKET socket(int af, int type, int protocol);

成功時返回套接字句柄,失敗返回 INVALID_SOCKET

3.調(diào)用 bind 函數(shù),為套接字分配 IP 地址和端口號

int bind(SOCKET s, const struct sockaddr * name, int namelen);

成功時返回 0,失敗返回 SOCKET_ERROR

4.調(diào)用 listen 函數(shù),監(jiān)聽客戶端連接

int listen(SOCKET s, int backlog);

成功時返回 0 ,失敗返回 SOCKET_ERROR 。

5.調(diào)用 accept 函數(shù),允許客戶端連接

SOCKET accept(SOCKET s, struct sockaddr * addr, int * addrlen);

成功時返回套接字句柄,失敗返回 INVALID_SOCKET 。

6.調(diào)用 send 函數(shù), 給連接的客戶端發(fā)送數(shù)據(jù)

int send(SOCKET s, const char * buf, int len, int flags):

成功時返回傳輸字節(jié)數(shù),失敗返回 SOCKET_ERROR 。

7.調(diào)用 recv 函數(shù),接收連接的客戶端發(fā)來的數(shù)據(jù)

int recv(SOCKET s, const char * buf, int len, int flags);

成功時返回接收字節(jié)數(shù),失敗返回 SOCKET_ERROR 。

8.調(diào)用 close 函數(shù),關(guān)閉套接字。

int closesocket(SOCKET s);

成功時返回 0 ,失敗時返回 SOCKET_ERROR

9.注銷 Winsock 相關(guān)庫

int WSACleanup(void);

成功時返回 0 ,失敗時返回 SOCKET_ERROR

2.2 客戶端

客戶端的實現(xiàn)過程如下圖所示。

在這里插入圖片描述

下面給出實現(xiàn)基于TCP的客戶端的常用函數(shù)。

1.創(chuàng)建 socket 套接字

SOCKET socket(int af, int type, int protocol);

成功時返回套接字句柄,失敗返回 INVALID_SOCKET。

2.調(diào)用connect函數(shù),發(fā)起連接請求

int connect(SOCKET s, const struct sockaddr * name, int namelen);

成功時返回 0,失敗返回 SOCKET_ERROR

3.調(diào)用 send 函數(shù), 給連接的服務(wù)端發(fā)送數(shù)據(jù)

int send(SOCKET s, const char * buf, int len, int flags):

成功時返回傳輸字節(jié)數(shù),失敗返回 SOCKET_ERROR 。

4.調(diào)用 recv 函數(shù),接收連接的服務(wù)端發(fā)來的數(shù)據(jù)

int recv(SOCKET s, const char * buf, int len, int flags);

成功時返回接收字節(jié)數(shù),失敗返回 SOCKET_ERROR 。

5.調(diào)用 close 函數(shù),斷開連接。

int closesocket(SOCKET s);

成功時返回 0 ,失敗時返回 SOCKET_ERROR

3. demo展示

3.1 服務(wù)端源代碼

回聲服務(wù)端的C++代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 1024

void ErrorHandling(char *message);

int main(int argc, char *argv[])
{
  WSADATA wsaData;
  SOCKET hServSock, hClntSock;
  char message[BUF_SIZE];
  int strLen, i;

  SOCKADDR_IN servAdr, clntAdr;
  int clntAdrSize;

  if (argc != 2)
  {
    printf("Usage : %s <port>\n", argv[0]);
    exit(1);
  }

  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    ErrorHandling("WSAStartup() error!");

  hServSock = socket(PF_INET, SOCK_STREAM, 0);
  if (hServSock == INVALID_SOCKET)
    ErrorHandling("socket() error");

  memset(&servAdr, 0, sizeof(servAdr));
  servAdr.sin_family = AF_INET;
  /*servAdr.sin_addr.s_addr = htonl(INADDR_ANY);*/
  servAdr.sin_addr.s_addr = inet_addr("127.0.0.1");
  servAdr.sin_port = htons(atoi(argv[1]));

  if (bind(hServSock, (SOCKADDR *)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
    ErrorHandling("bind() error");

  if (listen(hServSock, 5) == SOCKET_ERROR)
    ErrorHandling("listen() error");

  clntAdrSize = sizeof(clntAdr);

  for (i = 0; i < 5; i++)
  {
    hClntSock = accept(hServSock, (SOCKADDR *)&clntAdr, &clntAdrSize);
    if (hClntSock == -1)
      ErrorHandling("accept() error");
    else
      printf("Connected client %d \n", i + 1);

    while ((strLen = recv(hClntSock, message, BUF_SIZE, 0)) != 0)
      send(hClntSock, message, strLen, 0);

    closesocket(hClntSock);
  }

  closesocket(hServSock);
  printf("game over");
  WSACleanup();
  return 0;
}

void ErrorHandling(char *message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}

注意:運行服務(wù)端代碼時,須加入命令行參數(shù)(端口號)。如代碼所示, IP 地址已經(jīng)綁定 127.0.0.1。配置 tasks.json 如下所示。

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "C/C++: g++.exe build active file",
      "command": "E:\\mingw64\\bin\\g++.exe",
      "args": [
        "-g",
        "${file}",
        "-lws2_32",
        "-o",
        "${fileDirname}\\${fileBasenameNoExtension}.exe"
      ],
      "options": {
        "cwd": "${workspaceFolder}"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

配置信息 launch.json 如下 。

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "(gdb) 啟動",
      "type": "cppdbg",
      "request": "launch",
      "program": "${fileDirname}/${fileBasenameNoExtension}.exe",
      "args": ["9190"],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "miDebuggerPath": "E:\\mingw64\\bin\\gdb.exe",
      "setupCommands": [
        {
          "description": "為 gdb 啟用整齊打印",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}

3.2 客戶端源代碼

回聲客戶端的C++代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#define BUF_SIZE 1024

void ErrorHandling(char *message);

int main(int argc, char *argv[])
{
  WSADATA wsaData;
  SOCKET hSocket;
  char message[BUF_SIZE];
  int strLen;
  SOCKADDR_IN servAdr;

  if (argc != 3)
  {
    printf("Usage : %s <IP> <port>\n", argv[0]);
    exit(1);
  }

  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    ErrorHandling("WSAStartup() error!");

  hSocket = socket(PF_INET, SOCK_STREAM, 0);
  if (hSocket == INVALID_SOCKET)
    ErrorHandling("socket() error");
  printf("%s\n", argv[0]);
  printf("%s\n", argv[1]);
  printf("%s\n", argv[2]);
  memset(&servAdr, 0, sizeof(servAdr));
  servAdr.sin_family = AF_INET;
  servAdr.sin_addr.s_addr = inet_addr(argv[1]);
  servAdr.sin_port = htons(atoi(argv[2]));
  if (connect(hSocket, (SOCKADDR *)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
    ErrorHandling("connect() error!");
  else
    puts("Connected...........");

  while (1)
  {
    fputs("Input message(Q to quit): ", stdout);
    fgets(message, BUF_SIZE, stdin);

    if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
      break;

    send(hSocket, message, strlen(message), 0);
    strLen = recv(hSocket, message, BUF_SIZE - 1, 0);
    printf("Message from server: %s", message);
  }

  closesocket(hSocket);
  WSACleanup();
  return 0;
}

void ErrorHandling(char *message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}

同樣,客戶端也需要加入命令行參數(shù) 127.0.0.1 9190運行??梢酝ㄟ^修改配置文件生成客戶端。
也可以通過cmd或者終端生成客戶端。cmd 方式如下:
首先通過 g++ 編譯器對 client.cpp 文件進(jìn)行編譯生成 .exe 文件。
之后在終端中,輸入 client.exe 127.0.0.1 9190 即可創(chuàng)建客戶端。

3.3 運行結(jié)果

服務(wù)端可以服務(wù) 5 個客戶端,即 accept 隊列長度為 5。
客戶端的運行結(jié)果如下,前5個客戶端均與服務(wù)端連接成功,可以收到“回聲”。第6次連接時,由于服務(wù)端斷開連接,所以產(chǎn)生連接錯誤。

在這里插入圖片描述
在這里插入圖片描述

服務(wù)端的運行結(jié)果如下圖所示。服務(wù)端可以連接5個客戶端,之后服務(wù)端將斷開連接。并顯示 “game over”。

在這里插入圖片描述

參考鏈接

深入理解TCP協(xié)議與UDP協(xié)議的原理及區(qū)別

VScode官方文檔

到此這篇關(guān)于Windows下VScode實現(xiàn)簡單回聲服務(wù)的文章就介紹到這了,更多相關(guān)VScode回聲服務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • QT5交叉編譯入門級教程(arm64、mips64)

    QT5交叉編譯入門級教程(arm64、mips64)

    交叉編譯就是在當(dāng)前系統(tǒng)平臺上,開發(fā)編譯運行于其它平臺的程序,比如本文硬件環(huán)境是x86平臺,但是編譯出來的程序是在arm64架構(gòu)、mips64等架構(gòu)上運行,本文給大家分享QT5交叉編譯入門級教程(arm64、mips64),感興趣的朋友一起看看吧
    2023-11-11
  • java string對象上的操作,常見的用法你知道嗎

    java string對象上的操作,常見的用法你知道嗎

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Java String類用法展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-08-08
  • C++單例設(shè)計模式詳細(xì)講解

    C++單例設(shè)計模式詳細(xì)講解

    單例模式(Singleton Pattern)是最簡單的設(shè)計模式之一。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式,這種模式涉及到一個單一的類,該類負(fù)責(zé)創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建
    2022-06-06
  • C++淺析虛函數(shù)使用方法

    C++淺析虛函數(shù)使用方法

    對C++了解的人都應(yīng)該知道虛函數(shù)(Virtual Function)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實現(xiàn)的。簡稱為V-Table。本文就將詳細(xì)講講虛函數(shù)表的原理與使用,需要的可以參考一下
    2022-08-08
  • C++取得本機(jī)IP的方法

    C++取得本機(jī)IP的方法

    這篇文章主要介紹了C++取得本機(jī)IP的方法,代碼簡單功能實用,具有不錯的借鑒參考價值,需要的朋友可以參考下
    2014-10-10
  • openCV實現(xiàn)圖像分割

    openCV實現(xiàn)圖像分割

    這篇文章主要為大家詳細(xì)介紹了openCV實現(xiàn)圖像分割,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C語言中fgets和fscanf區(qū)別詳解

    C語言中fgets和fscanf區(qū)別詳解

    這篇文章主要介紹了C語言中fgets和fscanf區(qū)別詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • short與int轉(zhuǎn)換的小例子

    short與int轉(zhuǎn)換的小例子

    short與int轉(zhuǎn)換的小例子,需要的朋友可以參考一下
    2013-04-04
  • C++利用類實現(xiàn)矩陣的數(shù)乘,乘法以及點乘

    C++利用類實現(xiàn)矩陣的數(shù)乘,乘法以及點乘

    這篇文章主要為大家詳細(xì)介紹了C++如何利用類實現(xiàn)矩陣的數(shù)乘,乘法以及點乘,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下
    2022-11-11
  • C++多線程中的鎖和條件變量使用教程

    C++多線程中的鎖和條件變量使用教程

    這篇文章主要介紹了C++多線程中的鎖和條件變量使用,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-11-11

最新評論

永善县| 安多县| 柘荣县| 丹阳市| 那曲县| 娄底市| 塘沽区| 荃湾区| 威信县| 合川市| 咸阳市| 昭苏县| 十堰市| 桂林市| 黑水县| 旺苍县| 霞浦县| 洪雅县| 兴安县| 青龙| 通许县| 平顺县| 密云县| 庐江县| 汶川县| 枣强县| 惠东县| 金湖县| 龙山县| 新巴尔虎左旗| 华亭县| 阿拉善右旗| 翼城县| 花莲县| 景宁| 克拉玛依市| 湟源县| 吉木萨尔县| 清涧县| 石门县| 哈尔滨市|