TCP服務器—實現數據通信

目錄

前言

1.接口介紹

2.編寫服務器

3.編寫客戶端

4.編譯鏈接

5.測試

6.總結


前言

? ? ? ? 今天我們要介紹的是使用TCP協議實現數據通信,相比于之前寫的UDP服務器實現數據信,在主體邏輯上并沒有差別。客戶端向服務器發送信息,服務器接受信息并回顯,因為UDP是面向數據報,而TCP是面向連接的,所以在實現的時候接口上會有一些差別,下面,我們具體來看看UDP和TCP在編碼的實現上有什么不同。

1.接口介紹

因為TCP是面向連接的,所以服務器創建完套接字,然后綁定成功后,將套接字設置為監聽套接字

服務器啟動之后,首先需要根據監聽套接字建立連接,建立連接成功后返回一個新的文件描述符,后續的通信都是按照這個新的文件描述符按照讀寫文件的形式進行讀寫數據。

對于客戶端來說創建完套接字之后,客戶端啟動之后首先需要建立連接

listen():設置sock為監聽狀態

 #include <sys/types.h>       #include <sys/socket.h>int listen(int sockfd, int backlog);

sockfd:創建套接字的返回值

backlog:底層全連接隊列的長度

accept():服務端建立連接

#include <sys/types.h>         
#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:監聽套接字

struct sockaddr* addr:輸出型參數,可以獲取服務端的IP地址和port端口號

socklen_t* addrlen:結構體的大小

返回值:返回一個新打開的文件描述符

connect():客戶端建立連接

#include <sys/types.h>        
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd:創建套接字返回值

struct sockaddr* addr:輸出型參數,用來填寫需要訪問的服務端的IP地址和port端口號

socklen_t addrlen:結構體的大小

2.編寫服務器

tcpServer.hpp

#pragma once#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "log.hpp"
namespace server
{using namespace std;enum{USAGE_ERR = 1,SOCKET_ERR,BIND_ERR,LISTEN_ERR};static const uint16_t gport = 8080;static const int gback = 5;class TcpServer{public:TcpServer(const uint16_t &port = gport): _port(gport), _sock(-1){}void InitServer(){_sock = socket(AF_INET, SOCK_STREAM, 0);if (_sock < 0){logMessage(FATAL, "create socket error");exit(SOCKET_ERR);}logMessage(NORMAL, "create socket success");// 綁定:struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;if (bind(_sock, (struct sockaddr *)&local, sizeof(local)) < 0){logMessage(FATAL, "bind socket error");exit(BIND_ERR);}logMessage(NORMAL, "bind socket success");// 設置sock為監聽狀態:if (listen(_sock, gback) < 0){logMessage(FATAL, "listen socket error");exit(LISTEN_ERR);}logMessage(NORMAL, "listen socket success");}void start(){for (;;){// 建立連接:struct sockaddr_in peer;socklen_t len = sizeof(peer);int sock = accept(_sock, (struct sockaddr *)&peer, &len); if (sock < 0){logMessage(ERROR, "accept error, next");continue;}logMessage(NORMAL, "accept a new link success");std::cout << "sock: " << sock << std::endl;//未來通信全部用sock,面向字節流的,后續全部都是文件操作:serviceIO(sock);close(sock);}}void serviceIO(int sock){char buffer[1024];while(true){ssize_t n = read(sock,buffer,sizeof(buffer)-1);if(n > 0){buffer[n] = 0;cout << "recvice message: " << buffer << endl;string outbuffer = buffer;outbuffer += "[server echo]";write(sock,outbuffer.c_str(),outbuffer.size());}else if(n == 0){// 代表client退出logMessage(NORMAL, "client quit, me too!");break;}}}~TcpServer(){}private:int _sock;uint16_t _port;};
}

tcpServer.cc:啟動服務器

#include"tcpServer.hpp"
#include<memory>
using namespace server;
static void Usage(string proc)
{cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}
int main(int argc,char* argv[])
{if(argc != 2){Usage(argv[0]);exit(USAGE_ERR);}uint16_t port = atoi(argv[1]);unique_ptr<TcpServer> tcs(new TcpServer(port));tcs->InitServer();tcs->start();return 0;
}

3.編寫客戶端

tcpClient.hpp

#pragma once#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>namespace client
{using namespace std;class TcpClient{public:TcpClient(const string& serverip,const uint16_t port):_serverip(serverip),_port(port),_sock(-1){}void InitClient(){_sock = socket(AF_INET,SOCK_STREAM,0);if(_sock < 0){cerr << "create sock fail" << endl;exit(-1);}}void start(){//建立連接:struct sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(_port);server.sin_addr.s_addr = inet_addr(_serverip.c_str());if(connect(_sock,(struct sockaddr*)&server,sizeof(server)) != 0){cerr << "connect fail" << endl;}else{string message;while(true){cout << "Please Enter: ";getline(cin,message);write(_sock,message.c_str(),message.size());char buffer[1024];int n = read(_sock,buffer,sizeof(buffer)-1);if(n > 0){buffer[n] = 0;cout << "Server回復: " << buffer << endl;}else{break;}}}}~TcpClient(){if(_sock >= 0)close(_sock);}private:string _serverip;uint16_t _port;int _sock;};
} // namespace client

tcpClient.cc:啟動客戶端

#include"tcpClient.hpp"
#include<memory>
using namespace client;
static void Usage(string proc)
{cout << "\nUsage:\n\t" << proc << " serverip serverport\n\n";
}
int main(int argc,char* argv[])
{if(argc != 3){Usage(argv[0]);exit(-1);}uint16_t port = atoi(argv[2]);string ip = argv[1];unique_ptr<TcpClient> tcc(new TcpClient(ip,port));tcc->InitClient();tcc->start();return 0;
}

4.編譯鏈接

makefile:

.PHONY:all
all:tcpServer tcpClient
tcpServer:tcpServer.ccg++ -o $@ $^ -std=c++11
tcpClient:tcpClient.ccg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm tcpServer tcpClient

5.測試

?如圖所示,服務端和客戶端可以完成正常的數據通信了。

6.總結

????????TCP協議和UDP協議在數據通信的實現中,除了一些接口使用的不同之外,其實并沒有太大的不同,在之前說的UDP是面向數據報的而TCP是面向字節流的,這些特性又是如何體現的呢?關于這個問題,博主將在后面的文章中會為大家繼續進行介紹。不要錯過哦!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/39761.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/39761.shtml
英文地址,請注明出處:http://en.pswp.cn/news/39761.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JavaEE初階:多線程 - Thread 類的基本用法

上次我們了解了多線程的五種創建方法&#xff0c;今天來學習Thread的基本用法。 目錄 run和start Thread常見的構造方法 Thread的幾個常見屬性 后臺線程 是否存活 線程終止 1.使用標志位 2.使用Thread自帶的標志 等待線程 run和start 首先需要理解Thread的run和star…

JavaWeb-Listener監聽器

目錄 監聽器Listener 1.功能 2.監聽器分類 3.監聽器的配置 4.ServletContext監聽 5.HttpSession監聽 6.ServletRequest監聽 監聽器Listener 1.功能 用于監聽域對象ServletContext、HttpSession和ServletRequest的創建&#xff0c;與銷毀事件監聽一個對象的事件&#x…

Python源碼05:使用Pyecharts畫詞云圖圖

**Pyecharts是一個用于生成 Echarts 圖表的 Python 庫。Echarts 是一個基于 JavaScript 的數據可視化庫&#xff0c;提供了豐富的圖表類型和交互功能。**通過 Pyecharts&#xff0c;你可以使用 Python 代碼生成各種類型的 Echarts 圖表&#xff0c;例如折線圖、柱狀圖、餅圖、散…

Glide 的超時控制相關處理

作者&#xff1a;newki 前言 Glide 相信大家都不陌生&#xff0c;各種源碼分析&#xff0c;使用介紹大家應該都是爛熟于心。但是設置 Glide 的超時問題大家遇到過沒有。 我遇到了&#xff0c;并且掉坑里了&#xff0c;情況是這樣的。 調用接口從網絡拉取用戶頭像&#xff0c…

3.微服務概述

1.大型網絡架構變遷 SOA與微服務最大的差別就是服務拆分的細度&#xff0c;目前大多數微服務實際上是SOA架構&#xff0c;真正的微服務應該是一個接口對應一個服務器&#xff0c;開發速度快、成本高&#xff1b; 微服務SOA能拆分的就拆分是整體的&#xff0c;服務能放一起的都…

自動駕駛HMI產品技術方案

版本變更 序號 日期 變更內容 編制人 審核人 文檔版本 1 2 1.

【計算機網絡】13、ARP 包:廣播自己的 mac 地址和 ip

機器啟動時&#xff0c;會向外廣播自己的 mac 地址和 ip 地址&#xff0c;這個即稱為 arp 協議。范圍是未經過路由器的部分&#xff0c;如下圖的藍色部分&#xff0c;范圍內的設備都會在本地記錄 mac 和 ip 的綁定信息&#xff0c;若有重復則覆蓋更新&#xff08;例如先收到 ma…

【Spring】深入理解 Spring 事務及其傳播機制

文章目錄 一、Spring 事務是什么二、Spring 中事務的實現方法2.1 Spring 編程式事務&#xff08;手動&#xff09;2.1.1 編程式事務的使用演示2.1.2 編程式事務存在的問題 2.2 Spring 聲明式事務&#xff08;自動&#xff09;2.2.1 Transactional 作用范圍2.2.2 Transactional …

騰訊云GPU服務器GN7實例NVIDIA T4 GPU卡

騰訊云GPU服務器GN7實例搭載1顆 NVIDIA T4 GPU&#xff0c;8核32G配置&#xff0c;系統盤為100G 高性能云硬盤&#xff0c;自帶5M公網帶寬&#xff0c;系統鏡像可選Linux和Windows&#xff0c;地域可選廣州/上海/北京/新加坡/南京/重慶/成都/首爾/中國香港/德國/東京/曼谷/硅谷…

安卓純代碼布局開發游戲二:Android Studio開發環境搭建

1.Android Studio下載&#xff1a; Download Android Studio & App Tools - Android Developers 2.安裝 安裝過程非常簡單&#xff0c;找到下載包&#xff0c;一直點Next即可。 3.下載Android SDK 第一次進入Android Studio默認會先下載Android SDK,筆者下載的Android SDK存…

零售行業供應鏈管理核心KPI指標(三)

完美訂單滿足率和退貨率 完美訂單滿足率有三個方面的因素影響&#xff1a;訂單按時、足量、無損交貨。通常情況下零售企業追求線上訂單履行周期慢慢達到行業平均水平&#xff0c;就是交付的速度變快了&#xff0c;這個肯定是一件好事情&#xff0c;趨勢越來越好。 同時&#…

歐拉公式

文章目錄 歐拉公式e歐拉恒等式歐拉公式歐拉公式 推導2步驟1: 使用泰勒級數展開步驟2: 將 i x i x ix 代入 e x e^x ex 復平面上推導歐拉公式步驟1&#xff1a;復平面上的復數表示步驟2&#xff1a;定義復數的指數形式步驟3&#xff1a;求導步驟4&#xff1a;連接兩種形式步驟…

ubuntu安裝opencv4

apt 安裝 sudo apt install libopencv-dev python3-opencvpkg-config查看安裝 sudo apt install pkg-configpkg-config --modversion opencv4pkg-config --libs --cflags opencv4參考 如何在 Ubuntu 20.04 上安裝 OpenCV pkg-config 詳解

spark yarn 開啟動態資源分配

概念 不需要指定并發&#xff0c;只需要指定內存&#xff0c; 程序在運行后會動態調節并發數量&#xff0c;我們只需要設置一個上線即可 在spark 配置文件設置&#xff1a; spark.dynamicAllocation.enabled true spark.shuffle.service.enabled true 準備shuffer jar 將spar…

星際爭霸之小霸王之小蜜蜂(一)

目錄 前言 一、安裝pygame庫 1、pygame庫簡介 2、在windows系統安裝pygame庫 二 、搭建游戲框架 1、創建游戲窗口 2、改變窗口顏色 總結 前言 大家應該都看過或者都聽說過python神書“大蟒蛇”&#xff0c;上面有一個案例是《外星人入侵》&#xff0c;游戲介紹讓我想起了上…

炫酷UI前端效果的CSS生成工具

提升設計人員和前端開發人員的工作 推薦炫酷UI前端效果的CSS生成工具1.Neumorphism2.帶有漸變的圖標3.Interactions4.大型數據庫5.動畫6.Mask7.動畫按鈕8. 自定義形狀分隔線9.背景圖案10. SVG波浪推薦炫酷UI前端效果的CSS生成工具 1.Neumorphism 地址:https://neumorphism.i…

【Nginx17】Nginx學習:目錄索引、字符集與瀏覽器判斷模塊

Nginx學習&#xff1a;目錄索引、字符集與瀏覽器判斷模塊 今天要學習的內容有幾個還是大家比較常見的&#xff0c;所以學習起來也不會特別費勁。對于目錄的默認頁設置大家都不會陌生&#xff0c;字符集的設置也比較常見&#xff0c;而瀏覽器的判斷這一塊&#xff0c;可能有同學…

深入源碼分析kubernetes informer機制(二)Reflector

[閱讀指南] 這是該系列第二篇 基于kubernetes 1.27 stage版本 為了方便閱讀&#xff0c;后續所有代碼均省略了錯誤處理及與關注邏輯無關的部分。 文章目錄 Reflector是什么整體結構工作流程list拉取數據緩存resync操作watch監聽操作 總結 Reflector是什么 reflector在informer…

RocketMQ雙主雙從同步集群部署

&#x1f388; 作者&#xff1a;互聯網-小啊宇 &#x1f388; 簡介&#xff1a; CSDN 運維領域創作者、阿里云專家博主。目前從事 Kubernetes運維相關工作&#xff0c;擅長Linux系統運維、開源監控軟件維護、Kubernetes容器技術、CI/CD持續集成、自動化運維、開源軟件部署維護…

學習筆記十九:Pod常見的狀態和重啟策略

Pod常見的狀態和重啟策略 常見的pod狀態第一階段&#xff1a;第二階段&#xff1a;擴展&#xff1a; pod重啟策略測試Always重啟策略正常停止容器內的tomcat服務非正常停止容器里的tomcat服務 測試never重啟策略正常停止容器里的tomcat服務非正常停止容器里的tomcat服務 測試On…