【Socket编程】基于TCP协议实现客户端与服务端的通信

前言

由于TCP是面向连接的,所以在创建套接字之后还需要进入监听状态,监听状态下可以获取客户端的请求。获得请求之后,服务器需要接受连接,之后再处理事务。

实现服务端具体步骤

总的来说,TCP服务端主要实现以下步骤:

  1. 创建一个监听套接字对象,指定使用TCP协议
  2. 绑定套接字到特定的地址和端口号
  3. 调用listen方法,监听连接请求
  4. 接收连接,返回一个新的套接字用于与客户端通信,以及客户端的地址
  5. 处理请求
  6. 发送响应
  7. 本次连接结束,关闭套接字
  8. 服务器结束,关闭监听套接字

为了便于区分,我们将第一个创建的套接字称为监听套接字,监听套接字只获取连接。后创建的套接字用于处理业务。

实现客户端具体步骤

  1. 创建套接字
  2. 使用connect方法连接到服务器
  3. 发送请求
  4. 接收响应
  5. 关闭套接字,结束连接

实现服务端

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 <fstream>
#include <functional>
#include "InetAddr.hpp"
#include "Log.hpp"using namespace log_ns;const static int gport = 8888;
const static int gsockfd = -1;
const static int gblcklog = 8;using task_t = function<void()>;class TcpServer
{
private:
public:TcpServer(uint16_t port = gport): _port(port), _listensockfd(gsockfd), _isrunning(false){}void InitServer(){// 1.创建socket,选择TCP协议_listensockfd = socket(AF_INET, SOCK_STREAM, 0);if (_listensockfd < 0){LOG(FATAL, "socket create error\n");exit(1);}LOG(FATAL, "listen socket create success,sockfd is %d\n", _listensockfd);// 创建strcut sockaddr_instruct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;// 2. bindint res = bind(_listensockfd, (struct sockaddr *)&local, sizeof(local));if (res < 0){LOG(FATAL, "server listen bind failed\n");exit(1);}LOG(FATAL, "server listen bind success\n");// 3.设置监听状态if (listen(_listensockfd, gblcklog) < 0){LOG(FATAL, "listen error\n");exit(1);}LOG(INFO, "listen suceess\n");}void Loop(){_isrunning = true;while (_isrunning){struct sockaddr_in client;socklen_t len = sizeof(client);// 4.获取新连接int sockfd = accept(_listensockfd, (struct sockaddr *)&client, &len);if (sockfd < 0){LOG(WARNING, "accept error\n");continue;}InetAddr addr(client);LOG(INFO, "get a new link,client info:%s,sockfd is %d\n", addr.AddrStr().c_str(), sockfd);// 处理业务// v0--简单读取消息Service(sockfd, addr);}_isrunning = false;}void Service(int sockfd, InetAddr addr){while (true){// 接收消息char inbuff[1024];ssize_t n = read(sockfd, inbuff, sizeof(inbuff) - 1);if (n > 0){inbuff[n] = 0;LOG(INFO, "get message from client ,message is %s\n", inbuff);// 回响string echo_message = "[server say]# ";echo_message += inbuff;write(sockfd, echo_message.c_str(), echo_message.size());}else if (n == 0){LOG(INFO, "client %s quit\n", addr.AddrStr().c_str());break;}else{LOG(ERROR, "read error: %s\n", addr.AddrStr().c_str());break;}}close(sockfd);}private:uint16_t _port;int _listensockfd;bool _isrunning;
};

TcpServerMain.cpp

该文件定义了服务端对象,执行服务端逻辑

#include "TcpServer.hpp"
#include <iostream>
#include <memory>
int main(int argc, char *argv[])
{if (argc != 2){std::cerr << "Usage: " << argv[0] << " local-port" << std::endl;exit(0);}uint16_t port = std::stoi(argv[1]);std::unique_ptr<TcpServer> tcvr = make_unique<TcpServer>(port);tcvr->InitServer();tcvr->Loop();return 0;
}

实现客户端

TcpClientMain.cpp

该文件实现了客户端发送请求的逻辑

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>int main(int argc, char *argv[])
{if (argc != 3){std::cerr << "Usage : " << argv[0] << " server-ip  server-port\n"<< std::endl;exit(0);}std::string ip = argv[1];uint16_t port = std::stoi(argv[2]);// 1.创建sockfdint sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){std::cerr << "create socket error" << std::endl;exit(0);}struct sockaddr_in peer;memset(&peer, 0, sizeof(peer));peer.sin_family = AF_INET;inet_pton(AF_INET, ip.c_str(), &peer.sin_addr);peer.sin_port = htons(port);// 2.连接服务器int n = connect(sockfd, (struct sockaddr *)&peer, sizeof(peer));if (n < 0){std::cerr << "connect socket error" << std::endl;exit(2);}// 3.处理业务while (true){std::string message;std::cout << "Enter #";std::getline(std::cin, message);write(sockfd, message.c_str(), message.size());char echo_buff[1024];int res = read(sockfd, echo_buff, sizeof(echo_buff) - 1);if (res > 0){echo_buff[res] = 0;std::cout << echo_buff << std::endl;}else{break;}}close(sockfd);return 0;
}

运行结果在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/48643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

达梦数据库的系统视图v$dmwatcher

达梦数据库的系统视图v$dmwatcher 查询当前登录实例所对应的守护进程信息&#xff0c;注意一个守护进程可以同时守护多个组的实例&#xff0c;因此查询结果中部分字段&#xff08;N_GROUP、SWITCH_COUNT&#xff09;为守护进程的全局信息&#xff0c;并不是当前登录实例自身的…

0401-403组合逻辑电路的分析设计竞争冒险

组合逻辑电路的分析设计&竞争冒险 4.组合逻辑电路1.目录2.教学基本要求3.序 关于组合逻辑电路 4.1组合逻辑电路分析与设计一、组合逻辑电路分析二、组合逻辑电路的分析步骤&#xff1a;三、组合逻辑电路的分析举例例1 奇校验电路例2.对输入的二进制求反码例3.一个工厂发电的…

使用 PVE 自签 CA 证书签发新证书

前言 PVE 安装时会自动创建一个有效期 10 年的 CA 证书, 我们可以利用这个 CA 证书给虚拟机中的 Web 应用签发新的 TLS 证书用于提供 HTTPS 服务. 下面以 PVE 虚拟机中通过 Docker 跑的一个 雷池 应用为例进行演示. PVE 证书位置 官方文档: https://pve.proxmox.com/wiki/Pr…

服务攻防-框架安全(漏洞复现)

关闭靶场 sudo docker-compose down 运行此靶场 sudo docker-compose up -d 查看启动环境 sudo docker ps 运行dockers容器 docker exec -it 64052abd288b /bin/bash thinkphp框架 thinkphp 2 - rce漏洞复现 docker exec -it 731dbae0e0b5 /bin/bash 集成化工具扫描 可以命令…

十五届蓝桥杯JAVA B组题目详解(持续更新中)

试题 B: 类斐波那契循环数 我发现蓝桥杯的题目现在就是要费时间去理解&#xff0c;所以还是审题很重要&#xff0c;这道题的思路就是&#xff0c;一个n位数的前n个数&#xff0c;都是对应的位数上的值&#xff0c;比如说12345&#xff0c;五位数是吧&#xff0c;那数列S的前五位…

phpstudy下载使用以及搭建本地SQL labs靶场

一&#xff0c;PHP study 小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; (xp.cn) 1&#xff0c;下载。 根据自己电脑系统下载对应的版本。 双击exe文件运行 选择下载目录&#xff08;路径不能有中文名&#xff09;。 2&#xff0c;使用。 启动阿帕奇和MySQ…

数据库第二次作业

1.建立数据库 2.插入数据 3.完成查询 &#xff08;1&#xff09;、显示所有职工的基本信息。 &#xff08;2&#xff09;、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 &#xff08;3&#xff09;、求出所有职工的人数。 &#xff08;4&#xff09;、列…

组队学习——贝叶斯分类器

前言 本次数据继续沿用上一次主题的【组队学习——支持向量机-CSDN博客】 数据处理部分延续【组队学习——支持向量机】主题的处理办法对应划分训练集和验证集 模型选择 本次贝叶斯分类器模型的较多&#xff0c;常用的为高斯朴素贝叶斯分类器、多项式朴素贝叶斯分类器、伯努…

JavaWeb总结

终于结束了JavaWeb的学习&#xff0c;个人感觉其实就是学习客户端与服务端交互的中间件&#xff0c;以及服务端处理的逻辑&#xff0c;来帮助我们构建整个项目的运转逻辑&#xff0c;从客户端到服务器再到客户端&#xff0c;核心是围绕着一系列的请求和响应如何处理&#xff0c…

嵌入式Linux学习: platform 设备驱动实验

在Linux中&#xff0c;Platform&#xff08;平台&#xff09;机制是一个重要的设备驱动管理框架&#xff0c;它主要在Linux 2.6内核及以后的版本中引入。Platform机制的主要目的是提供一种统一的方式来管理那些不直接挂靠在传统物理总线&#xff08;如USB、PCI、I2C、SPI等&…

论文阅读:Speculative RAG: Enhancing Retrieval Augmented Generation through Drafting

论文地址&#xff1a;https://arxiv.org/abs/2407.08223 RAG 将 LLM 的生成能力与外部知识源相结合&#xff0c;以提供更准确和最新的响应。最近的 RAG 进展侧重于通过迭代 LLM 完善或通过 LLM 的额外指令调整获得自我批判能力来改进检索结果。在这项工作中&#xff0c;作者介…

编程中的智慧六:单例、原型、建造者

上一篇咱们结合Spring介绍了设计模式中的工厂模式相关方法&#xff0c;其实现在Java开发基本上都是基于Spring框架开发&#xff0c;所以后续我们在开发过程中基本上很少自己重写一个工厂模式&#xff0c;都是直接使用Spring来完成。今天咱们接着看剩下的创建型设计模式&#xf…

Dubbo学习笔记

Dubbo 简介 Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的一个高性能、轻量级的开源Java RPC框架&#xff0c;可以和Spring框架无缝集成。 其中文官网:https://dubbo.gitbooks.io/dubbo-user-book/content/ 特性和用法 架构 节点角色说明 节点角色…

应用层的重点协议

目录 一、DNS 二、NAT 1、技术背景 2、NAT机制IP转化过程 三、NAPT NAT技术的缺陷 四、HTTP 1、协议格式 2、HTTP请求 1&#xff09;method(方法) GET请求的特点 POST请求的特点 GET和POST的区别 2&#xff09;URL(网址) 基本格式 关于URL encode 3&#xff0…

el-table表头使用el-dropdown出现两个下拉框

问题描述&#xff1a;el-table在固定右边列时&#xff0c;表头使用el-dropdown会出现两个下拉框&#xff0c;如图所示&#xff1a; 解决方法&#xff1a; 1.只显示第一个下拉框&#xff0c;通过控制样式将其他的下拉框display:none; 2.如图所示&#xff0c;修改插槽写法&…

<数据集>学生课堂行为识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;13899张 标注数量(xml文件个数)&#xff1a;13899 标注数量(txt文件个数)&#xff1a;13899 标注类别数&#xff1a;8 标注类别名称&#xff1a;[js, tt, dk, zt, dx, zl, jz, xt] # 举手 js # 抬头听课 …

从FasterTransformer源码解读开始了解大模型(2.3)代码通读04

从FasterTransformer源码解读开始了解大模型&#xff08;2.3&#xff09;代码解读04-forward函数 写在前面的话 本篇的内容继续解读forward函数&#xff0c;从972行开始进行解读 零、embedding函数 让我们考虑一种不包含prefix_soft_prompt的情况&#xff0c;从999行的embe…

在 PostgreSQL 里如何实现数据的冷热数据分层存储的自动化策略调整?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 在 PostgreSQL 里如何实现数据的冷热数据分层存储的自动化策略调整 在 PostgreSQL 里如何实现数据的冷…

【数据分享】2013-2022年我国省市县三级的逐日SO2数据(excel\shp格式\免费获取)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000——2022年的省市县三级的逐日PM2.5数据和2013-2022年的省市县三级的逐日CO数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享的是我国2013——2022年的省…

mongodb数据导出与导入

一、先去检查mongodump mongodump --version 如果报 mongodump version: built-without-version-string 或者其他的较老的版本&#xff0c;直接去下载最新的【传送门】 【以Ubuntu18.04为例】 安装工具 假设你下载的是 .tgz 文件&#xff08;适用于 Linux 系统&#xff09;&am…