当前位置: 首页 > news >正文

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是面向字节流的,这些特性又是如何体现的呢?关于这个问题,博主将在后面的文章中会为大家继续进行介绍。不要错过哦!

相关文章:

TCP服务器—实现数据通信

目录 前言 1.接口介绍 2.编写服务器 3.编写客户端 4.编译链接 5.测试 6.总结 前言 今天我们要介绍的是使用TCP协议实现数据通信&#xff0c;相比于之前写的UDP服务器实现数据信&#xff0c;在主体逻辑上并没有差别。客户端向服务器发送信息&#xff0c;服务器接受信息并回…...

基于SpringBoot实现MySQL备份与还原

基于SpringBoot实现MySQL备份与还原&#xff0c;需求是在页面上对所有的平台数据执行备份和恢复操作&#xff0c;那么就需要使用代码去调用MySQL备份和恢复的指令&#xff0c;下面是具体实现步骤&#xff1b; MySQL备份表设计 CREATE TABLE IF NOT EXISTS mysql_backups (id …...

【VUE 监听用户滑动】

监听滑动方法 一. touchstart、touchmove、touchend二.v-touch三. 自定义指令 一. touchstart、touchmove、touchend 在 Vue 中监听用户往哪个方向滑动可以通过添加事件监听器&#xff0c;然后在事件回调函数中判断滑动方向。常用的事件监听器有touchstart、touchmove、touche…...

通义大模型:打造更智能、更灵活的自然语言处理技术

大家好&#xff0c;今天我想向大家介绍一款备受瞩目的自然语言处理技术——通义大模型。作为一种基于深度学习的人工智能技术&#xff0c;通义大模型能够模拟人类的思维方式&#xff0c;实现更智能、更灵活的自然语言处理&#xff0c;为我们的生活和工作带来了极大的便利。 在…...

Go 流程控制

if语句使用 package mainimport "fmt"func main() {score : 700if score 700 {fmt.Println("清华")}//if支持一个初始化语句 初始化语句和条件判断用;分割if a : 700; a 700 {fmt.Println("清华")}}清华 清华if_else使用 package mainimpor…...

Python opennsfw/opennsfw2 图片/视频 鉴黄 笔记

nsfw&#xff08; Not Suitable for Work&#xff09;直接翻译就是 工作的时候不适合看&#xff0c;真文雅 nsfw效果&#xff0c;注意底部的分数 大体流程&#xff0c;输入图片/视频&#xff0c;输出0-1之间的数字&#xff0c;一般情况下&#xff0c;Scores < 0.2 认为是非…...

四、Linux中cd、pwd以及相对/绝对路径和特殊路径符

1、cd命令&#xff1a; cd命令可以切换当前工作目录&#xff0c;基础语法是&#xff1a; cd [linux路径] &#xff08;1&#xff09;、打开Linux的命令提示行&#xff0c;当前工作目录是home&#xff0c;输入“cd /”&#xff0c;可以切换到根目录下&#xff0c;在根目录下输…...

第八章 CUDA内存应用与性能优化篇(上篇)

cuda教程目录 第一章 指针篇 第二章 CUDA原理篇 第三章 CUDA编译器环境配置篇 第四章 kernel函数基础篇 第五章 kernel索引(index)篇 第六章 kenel矩阵计算实战篇 第七章 kenel实战强化篇 第八章 CUDA内存应用与性能优化篇 第九章 CUDA原子(atomic)实战篇 第十章 CUDA流(strea…...

chrome浏览器改为黑色背景

chrome浏览器改为黑色背景 https://blog.csdn.net/yuchen_123456/article/details/127487278 不一样的地方&#xff1a;...

【AI】《动手学-深度学习-PyTorch版》笔记(十七):卷积神经网络入门

AI学习目录汇总 1、从全链接层到卷积 1.1 卷积 我们在前面学习的多层感知机中,已经认识了全链接层,缺点很明显,在稍微大点的网络模型中,参数成指数级别增长。参数量很快就达到数十亿,这样的量级几乎无法计算。为此科学家们想出一个减少参数的方法:卷积。 从全链接层到…...

element-ui table表格,根据缩放自适应

安装依赖 npm install af-table-columnmain.js 中引入依赖&#xff0c; import Vue from vue import ElementUI from element-ui //需要按需引入&#xff0c;先引入vue并引入element-ui import AFTableColumn from af-table-column Vue.use(AFTableColumn)demo样式&#xff1…...

【electron】electron安装过慢和打包报错:Unable to load file:

文章目录 一、安装过慢问题:二、打包报错&#xff1a;Unable to load file: 一、安装过慢问题: 一直处于安装过程 【解决】 #修改npm的配置文件 npm config edit#添加配置 electron_mirrorhttps://cdn.npm.taobao.org/dist/electron/二、打包报错&#xff1a;Unable to load…...

微服务部署中的动态扩缩容和故障迁移实践经验!快来看看!

随着微服务架构的快速普及&#xff0c;越来越多的组织开始将传统的单体应用转变为分布式的微服务系统。在这种架构下&#xff0c;动态扩缩容和故障迁移变得尤为重要&#xff0c;因为它们能够帮助我们应对不断变化的负载和故障情况。本文将详细介绍动态扩缩容和故障迁移的概念&a…...

代码随想录第四十五天

代码随想录第四十五天 Leetcode 70. 爬楼梯Leetcode 322. 零钱兑换Leetcode 279. 完全平方数 Leetcode 70. 爬楼梯 题目链接: 爬楼梯 自己的思路:之前是用斐波那契做的&#xff0c;但是现在学了完全背包&#xff0c;可以将m2拓展的更大一点&#xff0c;我们可以将楼顶n设为背包…...

Vue Baidu Map--自定义点图标bm-marker

自定义点图标 将准备好的图标放到项目中 使用import引入&#xff0c; 并在data中进行声明 <script> import mapIconRed from ./vue-baidu-map/img/marker_red_sprite.png export default {data() {return {mapIconRed,}}, } </script>在<bm-marker>中加入参…...

ZooKeeper的基本概念

集群角色 通常在分布式系统中&#xff0c;构成一个集群的每一台机器都有自己的角色&#xff0c;最典型的集群模式就是Master/Slave模式(主备模式)。在这种模式中&#xff0c;我们把能够处理所有写操作的机器称为Master机器&#xff0c;把所有通过异步复制方式获取最新数据&…...

SpringBoot复习:(51)默认情况下DataSource是怎么创建出来的,是什么类型的?

DataSource是通过DataSourceAutoConfiguration创建的&#xff0c;这个类代码如下&#xff1a; 可以看到DataSourceAutoConfiguration有个静态内部类PooledDataSourceConfiguration,在这个类上有个Import注解&#xff0c;导入了DataSourceConfiguration.Hikari这个类&#xff0…...

Python+Selenium自动化测试环境搭建步骤(selenium环境搭建)

一、自动化简介 1.自动化测试概念&#xff1a; 是把以人为驱动的测试转化为机器执行的一种过程&#xff0c;它是一种以程序测试程序的过程 2.自动化测试分类&#xff1a; 一般IT上所说的自动化测试是指功能自动化测试&#xff0c;通过编码的方式用一段程序来测试一个软件的功…...

实现简单纯Canvas文本输入框,新手适用

文章目录 概要效果技术细节代码 概要 Canvas上面提供输入&#xff1a; 一、最简单可能是用dom渲染一个input,覆盖在图形上面进行文本编辑&#xff0c;编辑完再把内容更新到图形.这样简单&#xff0c;但是缺点也明显&#xff0c;就是它不是真正绘制在canvas上面&#xff0c;没…...

React构建的JS优化思路

背景 之前个人博客搭建时&#xff0c;发现页面加载要5s才能完成并显示 问题 React生成的JS有1.4M&#xff0c;对于个人博客服务器的带宽来说&#xff0c;压力较大&#xff0c;因此耗费了5S的时间 优化思路 解决React生成的JS大小&#xff0c;因为我用的是react-router-dom…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

【iOS】 Block再学习

iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...

边缘计算网关提升水产养殖尾水处理的远程运维效率

一、项目背景 随着水产养殖行业的快速发展&#xff0c;养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下&#xff0c;而且难以实现精准监控和管理。为了提升尾水处理的效果和效率&#xff0c;同时降低人力成本&#xff0c;某大型水产养殖企业决定…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 &#x1f680; 深度解析&#xff1a;etcd 在 Milvus 向量数据库中的关键作用 &#x1f4a1; 什么是 etcd&#xff1f; &#x1f9e0; Milvus 架构简介 &#x1f4e6; etcd 在 Milvus 中的核心作用 &#x1f527; 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...