TCP socket

TCP的socket和UDP大同小异,基本的代码结构都是相同的。一些相同的接口本文就不赘述了,例如,socket,bind,有需要看这篇文章UDP socket

服务端server

两步:初始化服务端,运行服务端

初始化服务端

创建socket,bind IP和端口号,listen监听

socket的第二个参数使用SOCK_STREAM,因为与UDP不同的是TCP面向字节流。其余的与UDP无异。

listen接口

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 

    void init()
    {
        // socket
        sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd_ < 0)
        {
            exit(1);
        }
        // bind
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        inet_pton(AF_INET, ip_.c_str(), &local.sin_addr);
        local.sin_port = htons(port_);
        int n = bind(sockfd_, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            exit(2);
        }
        // listen
        if (listen(sockfd_, 10) < 0)
        {
            exit(3);
        }
    }

运行服务端

四步:accept接收请求,接收数据,处理数据,最后发送数据

accept接口

 初始化socket得到的文件描述符是用来listen的,而accept获得的文件描述符才是用来传输数据的,read和write接口就是用这个描述符的。

read和write很简单,第一个参数是文件描述符,第二个参数是读取/发送的数据地址,第三个参数是数据的大小

void run()
    {
        while (1)
        {
            // accept
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int lis_fd = accept(sockfd_, (struct sockaddr *)&client, &len);
            // 接收数据
            char buf[1024] = {0};
            int n = read(lis_fd, buf, sizeof(buf));
            if (n < 0)
            {
                break;
            }
            else if (n == 0)
            {
                cout << "quit" << endl;
                break;
            }
            else
            {
                buf[n] = 0;
                std::cout << "server get msg:" << buf << std::endl;
                // 处理数据
                std::string msg = "server say: I have get msg >_";
                msg += buf;
                write(lis_fd, msg.c_str(), msg.size());
            }
        }
    }

客户端client

五步:创建socket(同服务端)->bind(由OS完成)->connect请求连接->发送数据write->接收数据read

connect接口

第一个参数是socket获得的文件描述符,第二个是要连接的服务端的属性结构体(记得类型转换),TCP的结构体数据类型是struct sockaddr_in。第三个是结构体大小

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << argv[0] << "[ip]" << "[port]" << std::endl;
        return -1;
    }
    // 获取命令行参数
    uint16_t port = stoi(argv[2]);
    string ip = argv[1];
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip.c_str());

    

        
    while (1)
    {
        // socket
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
        {
            std::cout << "client create fail" << endl;
            exit(1);
        }
        // bind由os随机分配端口完成
        
        // connect
        int n = connect(sockfd, (struct sockaddr *)&server, (socklen_t)sizeof(server));
        if (n < 0)
        {
            std::cout << "client connect fail" << std::endl;
            exit(2);
        }

        std::string msg;
        std::cout << "Please Enter>_";
        getline(std::cin, msg);
        // 发送数据
        n = write(sockfd, msg.c_str(), msg.size());
        if (n < 0)
        {
            std::cout << "write fail" << std::endl;
            continue;
        }

        char buf[1024] = {0};
        // 接收数据
        n = read(sockfd, buf, sizeof(buf));
        if (n < 0)
        {
            std::cout << "read fail" << std::endl;
            continue;
        }
        buf[n] = 0;
        cout << buf << endl;
    }
}

序列化和反序列化

序列化是将数据结构或对象转换为一种可以存储或传输的格式,反序列化是序列化的逆过程,它将序列化后的数据重新还原为原始的对象或数据结构。

其实这本质和协议是一样的,都是一种约定。服务端和客户端都按照一个相同的规则将收发的数据做处理,以便于数据的传输。

序列化和反序列化的应用场景

  1. 网络编程

    客户端与服务器之间传输数据时,往往通过序列化和反序列化的方式来进行。例如,在你写的 TCP 客户端/服务器代码中,客户端需要将数据(如数学表达式)序列化后发送给服务器,服务器再反序列化处理并返回结果。
  2. 数据持久化

    将内存中的数据或对象序列化后保存到数据库或文件中,以便稍后可以重新加载数据并继续使用。
  3. 跨进程通信

    当两个不同的进程需要交换数据时,序列化可以将复杂数据结构转换为字节流,方便在进程之间传递。

源码

//tcpserver.hpp
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

enum
{
    SocketFail = 1,
    BindFail,
    ListenError
};
class tcpServer
{
public:
    tcpServer(std::string ip = "0.0.0.0", uint16_t port = 8888)
        : ip_(ip), port_(port)
    {
    }
    ~tcpServer()
    {
    }

    void init()
    {
        // socket
        sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd_ < 0)
        {
            exit(SocketFail);
        }
        // bind
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        inet_pton(AF_INET, ip_.c_str(), &local.sin_addr);
        local.sin_port = htons(port_);
        int n = bind(sockfd_, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            exit(BindFail);
        }
        // listen
        if (listen(sockfd_, 10) < 0)
        {
            exit(ListenError);
        }
    }

    void run()
    {
        while (1)
        {
            // accept
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int lis_fd = accept(sockfd_, (struct sockaddr *)&client, &len);
            // 接收数据
            char buf[1024] = {0};
            int n = read(lis_fd, buf, sizeof(buf));
            if (n < 0)
            {
                break;
            }
            else if (n == 0)
            {
                cout << "quit" << endl;
                break;
            }
            else
            {
                buf[n] = 0;
                std::cout << "server get msg:" << buf << std::endl;
                // 处理数据
                std::string msg = "server say: I have get msg >_";
                msg += buf;
                write(lis_fd, msg.c_str(), msg.size());
            }
        }
    }

private:
    int sockfd_;
    std::string ip_;
    uint16_t port_;
};
//tcpclient.cpp
#include <iostream>
#include <string>
#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::cout << argv[0] << "[ip]" << "[port]" << std::endl;
        return -1;
    }
    // 获取命令行参数
    uint16_t port = stoi(argv[2]);
    string ip = argv[1];
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip.c_str());

    

        
    while (1)
    {
        // socket
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
        {
            std::cout << "client create fail" << endl;
            exit(1);
        }
        // bind由os随机分配端口完成
        
        // connect
        int n = connect(sockfd, (struct sockaddr *)&server, (socklen_t)sizeof(server));
        if (n < 0)
        {
            std::cout << "client connect fail" << std::endl;
            exit(2);
        }

        std::string msg;
        std::cout << "Please Enter>_" << std::endl;
        getline(std::cin, msg);
        // 发送数据
        n = write(sockfd, msg.c_str(), msg.size());
        if (n < 0)
        {
            std::cout << "write fail" << std::endl;
            continue;
        }

        char buf[1024] = {0};
        // 接收数据
        n = read(sockfd, buf, sizeof(buf));
        if (n < 0)
        {
            std::cout << "read fail" << std::endl;
            continue;
        }
        buf[n] = 0;
        cout << buf << endl;
    }
}
//main.cpp
#include "tcpServer.hpp"
#include <memory>

int main()
{
    std::unique_ptr<tcpServer> server(new tcpServer);
    server->init();
    server->run();
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ML4T:把机器学习驱动交易做成标准的pipeline(流)的​模式

原创内容第652篇&#xff0c;专注量化投资、个人成长与财富自由。 量化的刚需是策略&#xff0c;策略的核心是因子。 ML4T&#xff08;Machine Learning for Trading&#xff09;&#xff0c;把机器学习驱动交易做成标准的pipeline(流)的模式。 对于机器而言&#xff0c;多数…

JDBC API详解一

DriverManager 驱动管理类&#xff0c;作用&#xff1a;1&#xff0c;注册驱动&#xff1b;2&#xff0c;获取数据库连接 1&#xff0c;注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); 查看Driver类源码 static{try{DriverManager.registerDriver(newDrive…

【目标检测数据集】锯子数据集1107张VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1107 标注数量(xml文件个数)&#xff1a;1107 标注数量(txt文件个数)&#xff1a;1107 标注…

AI donotpay平台介绍

AI donotpay平台介绍 DoNotPay 是一个基于人工智能的在线法律服务平台&#xff0c;旨在帮助用户解决与大公司和政府机构的各种问题。以下是对 DoNotPay 平台的详细介绍&#xff1a; 1. 平台概述 创始人: DoNotPay 由 Joshua Browder 于 2015 年创立&#xff0c;最初是一个用于…

店群合一模式下的社区团购新发展——结合链动 2+1 模式、AI 智能名片与 S2B2C 商城小程序源码

摘要&#xff1a;本文探讨了店群合一的社区团购平台在当今商业环境中的重要性和优势。通过分析店群合一模式如何将互联网社群与线下终端紧密结合&#xff0c;阐述了链动 21 模式、AI 智能名片和 S2B2C 商城小程序源码在这一模式中的应用价值。这些创新元素的结合为社区团购带来…

【0基础】制作HTML网页小游戏——贪吃蛇(附详细解析)

我在昨天的文章&#xff08;贪吃蛇HTML源码&#xff09;里面分享了网页版贪吃蛇小游戏的源码&#xff0c;今天就来给大家详细讲解一下每部分代码是如何运作的&#xff0c;以及以后要如何美化贪吃蛇的UI界面&#xff0c;在哪里修改等。 目录 一、代码运作 1、HTML结构: 2、C…

【有啥问啥】深入浅出马尔可夫链蒙特卡罗(Markov Chain Monte Carlo, MCMC)算法

深入浅出马尔可夫链蒙特卡罗&#xff08;Markov Chain Monte Carlo, MCMC&#xff09;算法 0. 引言 Markov Chain Monte Carlo&#xff08;MCMC&#xff09;是一类用于从复杂分布中采样的强大算法&#xff0c;特别是在难以直接计算分布的情况下。它广泛应用于统计学、机器学习…

rtems 5.3 qemu realview_pbx_a9 环境搭建:生成 rtems arm 工具链

前言 rtems 是一款比较优秀的 RTOS&#xff0c;官方网址 https://www.rtems.org/ 当前 rtems 最新发布的版本&#xff1a;rtems-5.3 版本&#xff0c; 下载地址 https://ftp.rtems.org/pub/rtems/releases/5/5.3/ rtems 支持的 平台也是比较多的&#xff0c;当前支持 STM32F4…

CSS 响应式设计(补充)——WEB开发系列36

随着移动设备的普及&#xff0c;网页设计的焦点逐渐转向了响应式设计。响应式设计不仅要求网页在各种屏幕尺寸上良好展示&#xff0c;还要适应不同设备的特性。 一、响应式设计之前的灵活布局 在响应式设计流行之前&#xff0c;网页布局通常是固定的或流动的。固定布局使用固定…

PMP–一、二、三模–分类–14.敏捷–技巧–项目生命周期

文章目录 技巧项目生命周期 一模14.敏捷--项目生命周期--原型法--迭代型生命周期&#xff0c;通过连续的原型或概念验证来改进产品或成果。每个新的原型都能带来新的干系人新的反馈和团队见解。题目中明确提到需要反馈&#xff0c;因此原型法比较好用。23、 [单选] 一个敏捷团队…

异常冲突行为和危险识别系统源码分享

异常冲突行为和危险识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Co…

Github 2024-09-16 开源项目周报 Top14

根据Github Trendings的统计,本周(2024-09-16统计)共有14个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4TypeScript项目2Go项目2JavaScript项目2Shell项目2Rust项目2C++项目2Jupyter Notebook项目1C#项目1React: 用于构建用户界面的JavaS…

linux第二课(docker的安装使用)

目录 一.关于docker (1)背景引入 (2)docker介绍 (3)功能 (4)Docker架构 二.docker的安装及相关的命令 (1)docker的安装 (2)docker的配置 (3)docker镜像命令 (4)容器命令 三.docker安装myaql ​编辑 四.数据卷挂载 1.数据卷挂载引入 2.数据卷挂载图解 3.数据卷的安装…

1. 运动控制指令概要(omron 机器自动化控制器)

机器自动化控制器——第一章 运动控制指令概要 1-1 运动控制指令PLCopen运动控制用功能块运动控制指令概要▶ 运动控制指令的种类▶ 状态变化▶ 运动控制指令的启动和状态▶ 异常处理▶ 执行运动控制指令时输入变量的变更(指令重启)▶ 通过选择缓存模式执行指令多重启动▶ 通过…

20Kg载重30分钟续航多旋翼无人机技术详解

一、机架与结构设计 1. 材料选择&#xff1a;为了确保无人机能够承载20Kg的负载&#xff0c;同时实现30分钟的续航&#xff0c;其机架材料需选用轻质高强度的材料&#xff0c;如碳纤维或铝合金。这些材料不仅具有良好的承重能力&#xff0c;还能有效减轻无人机的整体重量&…

【重学 MySQL】二十九、函数的理解

【重学 MySQL】二十九、函数的理解 什么是函数不同 DBMS 函数的差异函数名称和参数功能实现数据类型支持性能和优化兼容性和可移植性 MySQL 的内置函数及分类单行函数多行函数&#xff08;聚合函数&#xff09;使用注意事项 什么是函数 函数&#xff08;Function&#xff09;在…

【webpack4系列】设计可维护的webpack4.x+vue构建配置(终极篇)

文章目录 构建配置包设计通过多个配置文件管理不同环境的 webpack 配置抽离成一个 npm 包统一管理&#xff08;省略&#xff09;通过 webpack-merge 组合配置 功能模块设计目录结构设计构建配置插件安装webpack、webpack-cli关联HTML插件html-webpack-plugin解析ES6解析vue、JS…

InterPro蛋白质结构域数据下载

前言 偶然发现InterPro数据库挺不错的。 之前使用selenium爬取了AlphaFlod数据&#xff0c;于是也想试试把InterPro的结构域数据爬取一下。 结果发现官方已经给好了代码&#xff0c;真是太善解人意了。 当然&#xff0c;想要批量下载还需要魔改一下官方代码。 步骤一&#…

看Threejs好玩示例,学习创新与技术(三)

本文接上篇内容&#xff0c;继续挖掘应用ThreeJS的一些创新算法。 1、获得鼠标移动对应的地理位置 这个算法如果放在几年前&#xff0c;那肯定会难倒一帮人的。因为是三维投影涉及矩阵变换及求逆&#xff0c;而且还是投影模式下的。在Project Texture这个示例中&#xff0c;作…

【小鹏汽车用户平台-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…