网络套接字编程(TCP协议)

news2024/11/18 13:51:27

文章目录

    • 简单的TCP网络程序
    • 服务器绑定
    • 服务端监听
    • 服务端获取连接
    • 客户端连接服务器
    • 多线程版本的大小写字母转换服务

简单的TCP网络程序

int socket(int domain, int type, int protocol);

参数说明:

domain:创建套接字的域或者叫做协议家族,也就是创建套接字的类型。该参数就相当于struct sockaddr结构的前16个位。如果是本地通信就设置为AF_UNIX,如果是网络通信就设置为AF_INET(IPv4)或AF_INET6(IPv6)。

type:创建套接字时所需的服务类型。其中最常见的服务类型是SOCK_STREAM和SOCK_DGRAM,如果是基于UDP的网络通信,我们采用的就是SOCK_DGRAM,叫做用户数据报服务,如果是基于TCP的网络通信,我们采用的就是SOCK_STREAM,叫做流式套接字,提供的是流式服务。

protocol:创建套接字的协议类别。你可以指明为TCP或UDP,但该字段一般直接设置为0就可以了,设置为0表示的就是默认,此时会根据传入的前两个参数自动推导出你最终需要使用的是哪种协议。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

sockfd:创建套接字返回的文件描述符
addr:网络相关的属性
addrlen:传入的addr的长度

服务器绑定

class TcpSever
{
    void init()
    {
        _lisSock = socket(AF_INET, SOCK_STREAM, 0);

        if (_lisSock == -1)
        {
            cout << "error socket" << endl;
            exit(1);
        }

        cout << "sucess socket" << endl;

        //创建服务器信息
        sockaddr_in server;
        socklen_t len = sizeof(server);
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);

        _ip == "" ? server.sin_addr.s_addr = INADDR_ANY : inet_aton(_ip.c_str(), &server.sin_addr);

        //绑定服务器
        if (bind(_lisSock, (const sockaddr *)&server, len) == -1)
        {
            cout << "error bind" << endl;
            exit(1);

        }
        cout << "sucess bind" << endl;
   }

private:
    int _lisSock;    // 监听套接字
    string _ip;      // 服务器ip
    u_int16_t _port; // 服务器端口
};

服务端监听

int listen(int sockfd, int backlog);

参数说明:

sockfd:需要设置为监听状态的套接字对应的文件描述符。
backlog:全连接队列的最大长度。如果有多个客户端同时发来连接请求,此时未被服务器处理的连接就会放入连接队列,该参数代表的就是这个全连接队列的最大长度,一般不要设置太大,设置为5或10即可。

//监听_sock
if (listen(_lisSock, 5) == -1)
{
    cout << "error listen" << endl;
    exit(1);

}
cout << "sucess listen" << endl;

服务端获取连接

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数说明:

sockfd:特定的监听套接字,表示从该监听套接字中获取连接。
addr:对端网络相关的属性信息,包括协议家族、IP地址、端口号等。
addrlen:调用时传入期望读取的addr结构体的长度,返回时代表实际读取到的addr结构体的长度,这是一个输入输出型参数。

void load()
{
     //监听_sock
     if (listen(_lisSock, 5) == -1)
     {
         cout << "error listen" << endl;
         exit(1);

     }
     cout << "sucess listen" << endl;

     while (1)
     {
         sockaddr_in client;
         socklen_t len = sizeof(client);

         int sock = accept(_lisSock, (sockaddr *)&client, &len);
         if (sock == -1)
         {
             cout << "error sock" << endl;
             exit(1);

         }
         cout << "succes sock" << endl;
}

客户端连接服务器

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

sockfd:特定的套接字,表示通过该套接字发起连接请求。
addr:对端网络相关的属性信息,包括协议家族、IP地址、端口号等。
addrlen:传入的addr结构体的长度。

class TcpClient
{
    public:
    TcpClient(string serIp,uint16_t serPort):_serIp(serIp),_serPort(serPort)
    {}


    void start()
    {
        //套接字
        int _sock = socket(AF_INET,SOCK_STREAM,0);

        sockaddr_in server;
        socklen_t len=sizeof(server);

        server.sin_family=AF_INET;
        server.sin_port=htons(_serPort);
        inet_aton(_serIp.c_str(),&server.sin_addr);


        if(connect(_sock,(const sockaddr*)&server,len) == -1)
        {
            cout<<"error connet"<<endl;
            exit(1);
        }
        cout<<"connet sucess"<<endl;


    }

    ~TcpClient()
    {
        close(_sock);
    }
private:
    int _sock; //套接字
    string _serIp; // 服务器ip
    uint16_t _serPort; //服务器端口

};

多线程版本的大小写字母转换服务

server.hpp

class TcpSever;

struct Data
{
    Data(int sock,const string& ip,uint16_t port,TcpSever* TcpServer_this):_sock(sock),_ip(ip),_port(port),_TcpServer_this(TcpServer_this)
    {}

    int _sock;
    string _ip;
    uint16_t _port;
    TcpSever* _TcpServer_this;
};



class TcpSever
{
public:
    TcpSever(u_int16_t port, string ip = "") : _lisSock(-1), _port(port), _ip(ip)
    {
    }

    void init()
    {
        _lisSock = socket(AF_INET, SOCK_STREAM, 0);

        if (_lisSock == -1)
        {
            cout << "error socket" << endl;
            exit(1);
        }

        cout << "sucess socket" << endl;

        //创建服务器信息
        sockaddr_in server;
        socklen_t len = sizeof(server);
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);

        _ip == "" ? server.sin_addr.s_addr = INADDR_ANY : inet_aton(_ip.c_str(), &server.sin_addr);

        //绑定服务器
        if (bind(_lisSock, (const sockaddr *)&server, len) == -1)
        {
            cout << "error bind" << endl;
            exit(1);

        }
        cout << "sucess bind" << endl;


        // 线程池的创建
        _tp=threadPool<Task>::getinstance();
    }

    void load()
    {
        //监听_sock
        if (listen(_lisSock, 5) == -1)
        {
            cout << "error listen" << endl;
            exit(1);

        }
        cout << "sucess listen" << endl;

        while (1)
        {
            sockaddr_in client;
            socklen_t len = sizeof(client);

            int sock = accept(_lisSock, (sockaddr *)&client, &len);
            if (sock == -1)
            {
                cout << "error sock" << endl;
                exit(1);

            }
            cout << "succes sock" << endl;

            string client_ip = inet_ntoa(client.sin_addr);
            u_int16_t client_port = ntohs(client.sin_port);


            // 多线程版本
            Data d(sock,client_ip,client_port,this);
            pthread_t tid;
            pthread_create(&tid,nullptr,Routine,&d);


    }
    static void* Routine(void* args)
    {
        Data* pd = (Data*) args;

        pd->_TcpServer_this->LotoUp(pd->_sock,pd->_ip,pd->_port);
    }

    //翻译大小写
    void LotoUp(int sock, string ip, u_int16_t port)
    {
        cout<<"sucess LotoUp"<<endl;
        while (1)
        {

            char inbuf[1024];
            ssize_t s = read(sock, inbuf, 1024);
            if (s > 0)
            {
                inbuf[s]='\0';
                cout<<"before:"<<inbuf<<endl;
                for (int i = 0; i < s; i++)
                {
                    inbuf[i] = toupper(inbuf[i]);
                }

                cout<<"after:"<<inbuf<<endl;

                write(sock, inbuf, s);
                cout << ip << ":" << port << "   sucess LotoUp" << endl;
            }
            else if (s == 0)
            {
                cout << ip << ":" << port << "   quit LotoUp" << endl;
                break;
            }
            else
            {
                cout << ip << ":" << port << "   error LotoUp" << endl;
                break;
            }
        }

        close(sock);
    }



    ~TcpSever()
    {
    }

private:
    int _lisSock;    // 监听套接字
    string _ip;      // 服务器ip
    u_int16_t _port; // 服务器端口
};

int main()
{
    TcpSever server(8081);
    server.init();
    server.load();

    return 0;
}

client.hpp


class TcpClient
{
    public:
    TcpClient(string serIp,uint16_t serPort):_serIp(serIp),_serPort(serPort)
    {}
    void start()
    {
        //套接字
        int _sock = socket(AF_INET,SOCK_STREAM,0);

        sockaddr_in server;
        socklen_t len=sizeof(server);

        server.sin_family=AF_INET;
        server.sin_port=htons(_serPort);
        inet_aton(_serIp.c_str(),&server.sin_addr);


        if(connect(_sock,(const sockaddr*)&server,len) == -1)
        {
            cout<<"error connet"<<endl;
            exit(1);
        }
        cout<<"connet sucess"<<endl;
        bool quit=false;
        while(!quit)
        {   
            string outbuf;
            outbuf.clear();
            cout<<"请输入内容>>>";
            getline(cin,outbuf);

            if(outbuf == "quit")
            {
                quit=true;
            }

            ssize_t s = write(_sock,outbuf.c_str(),outbuf.size());

            if(s>0)
            {
                char inbuf[1024];
                ssize_t rs = read(_sock,inbuf,sizeof(inbuf));
                inbuf[rs]=0;
                cout<<inbuf<<endl;
            }

        }

    }

    ~TcpClient()
    {
        close(_sock);
    }
private:
    int _sock; //套接字
    string _serIp; // 服务器ip
    uint16_t _serPort; //服务器端口

};

int main()
{
    TcpClient client("127.0.0.1",8081);
    client.start();

    return 0;
}

效果
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

百万基建狂魔们的赛博世界

钉钉完成的&#xff0c;是基于PaaS底座和底层基础产品&#xff0c;与生态伙伴一起提供低代码的普惠化定制开发模式&#xff0c;让大型企业自己可以具备诊断自己的能力和梳理流程的能力&#xff0c;并且将过往的经验和积累进行数字化应用层面的表达&#xff0c;进而寻找出一条最…

ffplay调试环境搭建

前言 ffplay是基于FFmpeg的最简单的官方播放器。麻雀虽小&#xff0c;五脏俱全&#xff0c;虽说ffplay简单&#xff0c;但是各种播放器应有的功能一一俱全&#xff0c;说它简单或许仅仅是因为它只有一个点c文件而已吧。 想要开发一个优秀的播放器&#xff0c;参考是必不可少的&…

Netron可视化Pytorch保存的网络模型

目录 一.理清网络的输入与输出 二. 将模型转换为onnx格式 三.Netron可视化工具 一.理清网络的输入与输出 我自定义的网络模型&#xff08;主要看看前向传播函数即可&#xff09;&#xff1a; import torch import torch.nn as nn#导入数据预处理之后的相关数据 from dataP…

Acrel-EMS企业微电网能效管理平台在某食品加工厂35kV变电站应用-Susie 周

1、概述 该食品加工厂变电站工程规模&#xff1a;电压等级&#xff1a;35/10.5kV&#xff0c;规划主变容量16.3MVA1台8MVA。有一个总配电室&#xff0c;包括35kV开关柜、10kV开关柜和0.4kV配电柜&#xff0c;两个独立变压器室&#xff0c;变压器为干式变压器。35kV供电系统采用…

(2)ITK中迭代器的时间效率

背景 ITK对图像处理中&#xff0c;为了提高代码运行效率&#xff0c;通过迭代器Iterator可以实现对时间的优化。 在ITK的官方文档中也有明确的说明&#xff1a; 针对此说明&#xff0c;本次使用对图像获取最大值最小值的方式&#xff0c;来实验和测试其效率。 代码实现 &am…

JDBC 数据库连接池之Driud

1 数据库连接池简介 数据库连接池是个容器&#xff0c;负责分配、管理数据库连接(Connection) 它允许应用程序重复使用一个现有的数据库连接&#xff0c;而不是再重新建立一个&#xff1b; 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据…

数据安全新战场,EasyMR为企业筑起“安全防线”

2020年1月&#xff0c;时间跨度长达14年的&#xff0c;微软2.5亿条客户服务和支持记录在网上泄露&#xff1b; 同年4月&#xff0c;微盟发生史上最贵“删库跑路”事件&#xff0c;造成微盟市值一夜之间缩水约24亿港币&#xff1b; 今年7月&#xff0c;网信办依据《数据安全法…

PCIEBPMCx4板卡

PCIEBPMCx4本板卡可以使标准的PMC板卡安装于带有PCIE插槽的PC机上使用&#xff0c;安装后占一个槽位&#xff0c;槽位可以为PCIE x4 PCIE x8、PCIE x16&#xff0c;安装后工作在PCIE x4模式。PCIE X1 后开口也可以使用&#xff0c;但只运行在PCIE X1模式。PCIE支持X4 V2.0,板载…

Python对json的操作总结

Json简介&#xff1a;Json&#xff0c;全名 JavaScript Object Notation&#xff0c;是一种轻量级的数据交换格式。Json最广泛的应用是作为AJAX中web服务器和客户端的通讯的数据格式。现在也常用于http请求中&#xff0c;所以对json的各种学习&#xff0c;是自然而然的事情。 J…

C++学习笔记(十四)——vector的模拟实现

vector各函数接口总览 vector当中的成员变量介绍 默认成员函数 构造函数1 构造函数2 构造函数3 拷贝构造函数 赋值运算符重载函数 析构函数 迭代器相关函数 begin和end 容量和大小相关函数 size和capacity reserve resize empty 修改容器内容相关函数 push_ba…

centos8:安装java

一、背景 因为centos 8 安装Jenkins需要java环境&#xff0c;所以本文记录安装java环境过程。 二、环境 开发电脑&#xff1a;Windows 10 CentOS 8.4 64位 三、安装 3.1、java -version检查是否已安装 java -version 没有安装 3.2、检查系统是否自带jdk rpm -qa |grep …

Word控件Spire.Doc 【超链接】教程(1):如何在C#/VB.NET中给Word 文档插入超链接

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

系统移植 uboot 2

一、uboot源码获取 1.1 uboot官网获取 ftp://ftp.denx.de/pub/u-boot/ 前提是是芯片厂家将uboot源码开源到uboot官网上 1.2 ST开发社区获取 https://wiki.stmicroelectronics.cn/stm32mpu/wiki/STM32MP1_Developer_Package 1.3 ST官网 https://www.st.com/en/embedded-sof…

opcj3—人人开源三大套件的简单用法

renren开源是一个很不错的开源开发组件&#xff0c;人人开源 其中目前对我们最有用的有三个&#xff1a;renren-fast、renren-fast-vue和renren-generator。 renren-generator是核心服务&#xff0c;可以根据数据库自动生成从controller层到service层&#xff0c;再到持久层的…

.net开发安卓入门 - 环境安装

文章目录工具VS2022Android SDK Manager如下图&#xff0c;安装一个镜像和工具模拟器设备管理器如下图启动模拟器&#xff0c;看一下效果常见问题工具 VS2022 下载地址&#xff1a;https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?skuCom…

Linux邮件服务Postfix部署

我们看下邮件协议&#xff1a; 简单邮件传输协议&#xff08;SMTP&#xff09;&#xff1a;用于发送和中转出的电子邮件。使用TCP/25端口。 邮局协议版本&#xff08;POP3&#xff09;&#xff1a;用于将邮件存储到本地&#xff0c;占用服务器的TCP/110端口。 Internet 消息访问…

【Python游戏】一个csdn小编用Python语言写了一个足球游戏,成功模拟世界杯决赛现场

前言 halo&#xff0c;包子们下午好 最近世界杯不是很火呀 很多小伙伴应该都知道球赛反正买&#xff0c;别墅靠大海&#xff01; 今天就给大家实现一个类似世界杯的足球小游戏&#xff0c;咱就说真的堪比国足了&#xff01; 哈哈哈~ 好啦 直接开整&#xff01;&#xff01;&am…

「以代码作画」从数据角度剖析Art Blocks生成艺术

作者&#xff1a;Mia Bao, co-founder of thepass.to, chief partner of WHALE members 数据&#xff1a;Jin, data analyst of thepass.to 出品&#xff1a;ThePASS & BeepCrypto 文章数据&#xff1a;https://docs.google.com/spreadsheets/d/1zDun4eUTwA-BMU5Hl2c5EC…

基于SSM网上商城购物系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

目标检测算法——人体姿态估计数据集汇总 2(附下载链接)

&#x1f384;&#x1f384;近期&#xff0c;小海带在空闲之余收集整理了一批人体姿态估计数据集供大家参考。 整理不易&#xff0c;小伙伴们记得一键三连喔&#xff01;&#xff01;&#xff01;&#x1f388;&#x1f388; 目录 一、V-COCO数据集 二、宜家 ASM 数据集 三、…