国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux網(wǎng)絡(luò)編程——tcp套接字

這篇具有很好參考價(jià)值的文章主要介紹了Linux網(wǎng)絡(luò)編程——tcp套接字。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

本章Gitee倉(cāng)庫(kù):tcp套接字

主要代碼

客戶端:

#pragma once

#include"Log.hpp"

#include<iostream>
#include<cstring>

#include<sys/wait.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>

#include"threadPool.hpp"
#include"Task.hpp"

const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";
const int backlog = 5;  //不要設(shè)置太大
Log log;


enum{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    LITSEN_ERR
};
class TcpServer;

class ThreadData
{
public:
    ThreadData(int fd, const std::string &ip, const uint16_t &port, TcpServer *t)
    :t_sockfd_(fd), t_clientip_(ip), t_clientport_(port), t_tsvr_(t)
    {}
public:
    int t_sockfd_;
    std::string t_clientip_;
    uint16_t t_clientport_;
    TcpServer *t_tsvr_; //需要this指針
};

class TcpServer
{

public:
    TcpServer(const uint16_t &port, const std::string &ip = defaultip)
    :listensockfd_(defaultfd)
    ,port_(port)
    ,ip_(ip)
    {}

    //初始化服務(wù)器
    void Init()
    {
        //創(chuàng)建套接字
        listensockfd_ = socket(AF_INET, SOCK_STREAM, 0); //sock_stream提供字節(jié)流服務(wù)--tcp
        if(listensockfd_ < 0)
        {
            log(Fatal, "create socket, errno: %d, errstring: %s",errno, strerror(errno));
            exit(SOCKET_ERR);
        }

        log(Info, "create socket success, sockfd: %d",listensockfd_);

        int opt = 1;
        setsockopt(listensockfd_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));  //防止偶發(fā)性服務(wù)器無(wú)法進(jìn)行立即重啟

        //本地套接字信息
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        //填充網(wǎng)絡(luò)信息
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        inet_aton(ip_.c_str(), &(local.sin_addr));

        //bind
        int bd = bind(listensockfd_, (struct sockaddr*)&local, sizeof(local));
        if(bd < 0)
        {
            log(Fatal, "bind error, errno: %d, errstring: %s",errno, strerror(errno));
            exit(BIND_ERR);
        }
        log(Info, "bind success");


        //tcp面向連接, 通信之前要建立連接
        //監(jiān)聽(tīng)
        if(listen(listensockfd_, backlog) < 0)
        {
            log(Fatal, "listen error, errno: %d, errstring: %s",errno, strerror(errno));
            exit(LITSEN_ERR);
        }
        log(Info, "listen success");

    }

    static void *Routine(void *args)
    {
        pthread_detach(pthread_self());
        //子線程無(wú)需關(guān)閉文件描述符
        ThreadData *td = static_cast<ThreadData*>(args);

        td->t_tsvr_->Service(td->t_sockfd_, td->t_clientip_, td->t_clientport_);

        delete td;
    }

    void Start()
    {
        signal(SIGPIPE, SIG_IGN);
        threadPool<Task>::GetInstance()->Start();
        //signal(SIGCHLD, SIG_IGN);  //直接忽略進(jìn)程等待 V2
        log(Info, "server is running...");
        while(true)
        {
            //獲取新鏈接
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(listensockfd_, (struct sockaddr*)&client, &len);
            if(sockfd < 0)
            {
                log(Warning, "accpet error, errno: %d, errstring: %s",errno, strerror(errno));
                continue;
            }
            uint16_t clientport = ntohs(client.sin_port);
            char clientip[32];
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));
            log(Info, "get a new link..., sockfd: %d, clientip: %s, clientport: %d", sockfd, clientip, clientport);
            //根據(jù)新鏈接進(jìn)行通信
            
            //V1--單進(jìn)程
            //Service(sockfd, clientip, clientport);
            //close(sockfd);
            
            //V2--多進(jìn)程
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     //child
            //     close(listensockfd_);  //子進(jìn)程可以看到父進(jìn)程的文件描述符表,關(guān)閉不需要的 
            //     if(fork() > 0)  exit(0);//父進(jìn)程創(chuàng)建的子進(jìn)程直接退出
            //     Service(sockfd, clientip, clientport);  //孫子進(jìn)程執(zhí)行, 由于孫子的父進(jìn)程退出, 由系統(tǒng)領(lǐng)養(yǎng)
            //     close(sockfd);
            //     exit(0);
            // }
            // //father
            // close(sockfd);  //存在引用計(jì)數(shù),不會(huì)這個(gè)關(guān)閉這個(gè)文件
            // pid_t tid = waitpid(id, nullptr, 0);
            // (void)tid;
            
            //V3--多線程(創(chuàng)建進(jìn)程成本較高,換線程)
            // ThreadData *td = new ThreadData(sockfd, clientip, clientport, this);
            // pthread_t tid;
            // pthread_create(&tid, nullptr, Routine, td);
            //pthread_join(tid, nullptr);   //已進(jìn)行線程分離,無(wú)需等待(并發(fā)執(zhí)行)
            
            //V4--線程池
            Task t(sockfd, clientip, clientport);
            threadPool<Task>::GetInstance()->Push(t);

            //sleep(1); 
        }
    }
    void Service(int sockfd, const std::string &clientip, const uint16_t &clientport)
    {
        char buffer[4096];
        while(true)
        {
            ssize_t n = read(sockfd, buffer, sizeof(buffer));
            if(n > 0)
            {
                buffer[n] = 0;
                std::cout << "client say# " << buffer << std::endl;
                std::string echo_str = "tcpserver echo# ";
                echo_str += buffer;

                write(sockfd, echo_str.c_str(), echo_str.size());
            }
            else if(n == 0)
            {
                log(Info, "%s:%d quit, server close sockfd: %d", clientip.c_str(), clientport, sockfd);
                break;
            }
            else
            {
                log(Warning, "read error, sockfd: %d, clientip: %s, clientport: %d", sockfd, clientip.c_str(), clientport);
                break;
            }
            memset(buffer, 0, sizeof(buffer));
        }
    }

    ~TcpServer(){}
private:
    int listensockfd_;
    uint16_t port_;
    std::string ip_;
};

客戶端:

#include<iostream>
#include<cstring>
#include<unistd.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>

void Usage(const std::string &proc)
{
    std::cout << "\n\tUsage: " << proc << "serverip serverport" << std::endl;
}

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }

    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);

    // 填充信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr));



    //連接模塊
    while (true)
    {
        int sockfd = 0;
        int cnt = 5;
        bool isreconnect = false;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
        {
            std::cerr << "socket error" << std::endl;
            return 1;
        }
        do
        {
            // tcp客戶端也無(wú)需顯示bind
            // 向目標(biāo)發(fā)起連接(connect的時(shí)候進(jìn)行自動(dòng)隨機(jī)bind)
            int cn = connect(sockfd, (struct sockaddr *)&server, sizeof(server));
            if (cn < 0)
            {
                isreconnect = true;
                cnt--;  //重連5秒
                std::cerr << "connet error, reconnect: " << cnt << std::endl;
                close(sockfd);
                sleep(1);   //每隔一秒重連一次
            }
            else
            {
                break;
            }
        }while(cnt && isreconnect);

        if(cnt == 0)
        {
            std::cerr << "server offline..." << std::endl;
            break;
        }

        //服務(wù)模塊
        //while (true)
        {
            std::string message;
            std::cout << "Please Enter# ";
            std::getline(std::cin, message);
            if (message.empty())
                continue;

            int wn = write(sockfd, message.c_str(), message.size());
            if (wn < 0)
            {
                std::cerr << "write error" << std::endl;
                //break;
            }

            char inbuffer[4096];
            int rn = read(sockfd, inbuffer, sizeof(inbuffer));
            if (rn > 0)
            {
                inbuffer[rn] = 0;
                std::cout << inbuffer << std::endl;
            }
            else
            {
                //break;
            }
        }
        close(sockfd);
    }

    return 0;
}

關(guān)于構(gòu)造

關(guān)于構(gòu)造和初始化,可以直接在構(gòu)造的時(shí)候,將服務(wù)器初始化,那為什么還要寫到init初始化函數(shù)里面呢?

構(gòu)造盡量簡(jiǎn)單一點(diǎn),不要做一些“有風(fēng)險(xiǎn)”的操作。

listen監(jiān)聽(tīng)

tcp是面向連接的,通信之前要建立連接,服務(wù)器處于等待連接到來(lái)的狀態(tài):

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

Linux網(wǎng)絡(luò)編程——tcp套接字,Linux網(wǎng)絡(luò)編程,原創(chuàng),網(wǎng)絡(luò),linux,tcp/ip

accept

獲取新鏈接:

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

后兩個(gè)參數(shù)輸出型參數(shù),獲取對(duì)方的信息

這里返回也是一個(gè)套接字,這和最開(kāi)始創(chuàng)建的listensockfd_有什么區(qū)別呢?

這就好比去吃飯,門口有一個(gè)拉客的,問(wèn)“帥哥,來(lái)不來(lái)我們這里吃飯啊”,如果你去了,那就是“歡迎光臨,幾位呀”,你回答“我和我女朋友”,然后這個(gè)人大喊“兩位客人,來(lái)一個(gè)服務(wù)員”,這時(shí)候就來(lái)了一個(gè)服務(wù)員招呼你坐下,然后給你菜單,點(diǎn)完菜之后給你上菜;在這個(gè)期間站在門口的拉客的人,一直在招攬客人,有人來(lái)就喊服務(wù)員招招待,人家不來(lái)就繼續(xù)拉。

listensockdf_就是這個(gè)拉客的,真正給我們提供服務(wù)的是accept返回的

telnet測(cè)試

telnet可以對(duì)指定服務(wù)的遠(yuǎn)程連接

Linux網(wǎng)絡(luò)編程——tcp套接字,Linux網(wǎng)絡(luò)編程,原創(chuàng),網(wǎng)絡(luò),linux,tcp/ip

127.0.0.1本地環(huán)回,再加上端口號(hào)就可以測(cè)試了

ctrl + ],然后回車

讀取信息

tcp是面向字節(jié)流的,管道是面向字節(jié)流的、讀取普通文件也是面向字節(jié)流的,所以可以采用read進(jìn)行讀取。

掉線重連

當(dāng)讀端關(guān)閉之后,系統(tǒng)會(huì)殺掉寫端,采用signal(SIGPIPE, SIG_IGN)忽略這個(gè)信號(hào)

翻譯服務(wù)器演示

Linux網(wǎng)絡(luò)編程——tcp套接字,Linux網(wǎng)絡(luò)編程,原創(chuàng),網(wǎng)絡(luò),linux,tcp/ip文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-829838.html

到了這里,關(guān)于Linux網(wǎng)絡(luò)編程——tcp套接字的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux】TCP網(wǎng)絡(luò)套接字編程+協(xié)議定制+序列化和反序列化

    【Linux】TCP網(wǎng)絡(luò)套接字編程+協(xié)議定制+序列化和反序列化

    悟已往之不諫,知來(lái)者之可追。抓不住的就放手,屬于你的都在路上…… 1. 為了讓我們的代碼更規(guī)范化,所以搞出了日志等級(jí)分類,常見(jiàn)的日志輸出等級(jí)有DEBUG NORMAL WARNING ERROR FATAL等,再配合上程序運(yùn)行的時(shí)間,輸出的內(nèi)容等,公司中就是使用日志分類的方式來(lái)記錄程序的輸

    2024年02月08日
    瀏覽(25)
  • [Linux] 網(wǎng)絡(luò)編程 - 初見(jiàn)TCP套接字編程: 實(shí)現(xiàn)簡(jiǎn)單的單進(jìn)程、多進(jìn)程、多線程、線程池tcp服務(wù)器

    [Linux] 網(wǎng)絡(luò)編程 - 初見(jiàn)TCP套接字編程: 實(shí)現(xiàn)簡(jiǎn)單的單進(jìn)程、多進(jìn)程、多線程、線程池tcp服務(wù)器

    網(wǎng)絡(luò)的上一篇文章, 我們介紹了網(wǎng)絡(luò)變成的一些重要的概念, 以及 UDP套接字的編程演示. 還實(shí)現(xiàn)了一個(gè)簡(jiǎn)單更簡(jiǎn)陋的UDP公共聊天室. [Linux] 網(wǎng)絡(luò)編程 - 初見(jiàn)UDP套接字編程: 網(wǎng)絡(luò)編程部分相關(guān)概念、TCP、UDP協(xié)議基本特點(diǎn)、網(wǎng)絡(luò)字節(jié)序、socket接口使用、簡(jiǎn)單的UDP網(wǎng)絡(luò)及聊天室實(shí)現(xiàn)…

    2024年02月16日
    瀏覽(32)
  • 網(wǎng)絡(luò)編程【TCP流套接字編程】

    網(wǎng)絡(luò)編程【TCP流套接字編程】

    目錄 TCP流套接字編程 1.ServerSocket API 2.Socket API 3.TCP中的長(zhǎng)短連接 4.回顯程序(短連接) 5.服務(wù)器和客戶端它們的交互過(guò)程 6.運(yùn)行結(jié)果及修改代碼 ? ??兩個(gè)核心: ServerSocket? ? ?Socket 1.ServerSocket API ? ServerSocket 是創(chuàng)建?TCP服務(wù)端Socket的API ServerSocket 構(gòu)造方法: ServerSocket 方法 :

    2023年04月12日
    瀏覽(573)
  • 網(wǎng)絡(luò)編程套接字( TCP )

    網(wǎng)絡(luò)編程套接字( TCP )

    目錄 1、實(shí)現(xiàn)一個(gè)TCP網(wǎng)絡(luò)程序(單進(jìn)程版) ????????1.1、服務(wù)端serverTcp.cc文件 ?????????????????服務(wù)端創(chuàng)建套接字 ?????????????????服務(wù)端綁定 ?????????????????服務(wù)端監(jiān)聽(tīng) ?????????????????服務(wù)端獲取連接 ?????????????????服務(wù)

    2024年01月17日
    瀏覽(1816)
  • 【JaveEE】網(wǎng)絡(luò)編程之TCP套接字、UDP套接字

    【JaveEE】網(wǎng)絡(luò)編程之TCP套接字、UDP套接字

    目錄 1.網(wǎng)絡(luò)編程的基本概念 1.1為什么需要網(wǎng)絡(luò)編程? 1.2服務(wù)端與用戶端 1.3網(wǎng)絡(luò)編程五元組? 1.4套接字的概念 2.UDP套接字編程 2.1UDP套接字的特點(diǎn) ?2.2UDP套接字API 2.2.1DatagramSocket類 2.2.2DatagramPacket類? 2.2.3基于UDP的回顯程序 2.2.4基于UDP的單詞查詢? 3.TCP套接字編程 3.1TCP套接字的特

    2023年04月13日
    瀏覽(915)
  • 【JavaEE】網(wǎng)絡(luò)編程之TCP套接字、UDP套接字

    【JavaEE】網(wǎng)絡(luò)編程之TCP套接字、UDP套接字

    目錄 1.網(wǎng)絡(luò)編程的基本概念 1.1為什么需要網(wǎng)絡(luò)編程? 1.2服務(wù)端與用戶端 1.3網(wǎng)絡(luò)編程五元組? 1.4套接字的概念 2.UDP套接字編程 2.1UDP套接字的特點(diǎn) ?2.2UDP套接字API 2.2.1DatagramSocket類 2.2.2DatagramPacket類? 2.2.3基于UDP的回顯程序 2.2.4基于UDP的單詞查詢? 3.TCP套接字編程 3.1TCP套接字的特

    2023年04月20日
    瀏覽(120)
  • 【網(wǎng)絡(luò)編程】網(wǎng)絡(luò)編程套接字(三)TCP網(wǎng)絡(luò)程序

    【網(wǎng)絡(luò)編程】網(wǎng)絡(luò)編程套接字(三)TCP網(wǎng)絡(luò)程序

    與前邊的UDP網(wǎng)絡(luò)程序相同,創(chuàng)建套接字的接口都是socket,下邊對(duì)socket接口進(jìn)行介紹: 協(xié)議家族選擇AF_INET,因?yàn)槲覀円M(jìn)行網(wǎng)絡(luò)通信。 而第二個(gè)參數(shù),為服務(wù)類型,傳入SOCK_STREAM,我們編寫TCP程序,所以要選擇流式的服務(wù)。 第三個(gè)參數(shù)默認(rèn)傳入0,由前兩個(gè)參數(shù)就可以推出這是

    2024年02月16日
    瀏覽(92)
  • 網(wǎng)絡(luò)編程套接字應(yīng)用分享【Linux &C/C++ 】【UDP應(yīng)用 | TCP應(yīng)用 | TCP&線程池小項(xiàng)目】

    網(wǎng)絡(luò)編程套接字應(yīng)用分享【Linux &C/C++ 】【UDP應(yīng)用 | TCP應(yīng)用 | TCP&線程池小項(xiàng)目】

    目錄 前提知識(shí) 1. 理解源ip,目的ip和Macip 2. 端口號(hào) 3. 初識(shí)TCP,UDP協(xié)議 4.?網(wǎng)絡(luò)字節(jié)序 5. socket 編程 sockaddr類型? 一,基于udp協(xié)議編程? 1. socket——?jiǎng)?chuàng)建套接字 2. bind——將套接字強(qiáng)綁定? 3. recvfrom——接受數(shù)據(jù) 4. sendto——發(fā)出信息 ?遇到的問(wèn)題 (1. 云服務(wù)器中以及無(wú)法分配I

    2024年04月08日
    瀏覽(26)
  • 網(wǎng)絡(luò)編程套接字之三【TCP】

    網(wǎng)絡(luò)編程套接字之三【TCP】

    目錄 1. ServerSocket API(給服務(wù)器端使用的類) 2. Socket API(既給服務(wù)器使用,也給客戶端使用) 3. 寫TCP回顯—服務(wù)器 4. 使用線程池后的TCP服務(wù)器代碼(最終) 5. 寫回顯-客戶端 6. TCP回顯—客戶端代碼 7. 運(yùn)行回顯服務(wù)器和客戶端 TCP流套接字編程 ?ServerSocket 是創(chuàng)建TCP服務(wù)端Socket的

    2024年01月19日
    瀏覽(91)
  • 「網(wǎng)絡(luò)編程」第二講:socket套接字(四 - 完結(jié))_ Linux任務(wù)管理與守護(hù)進(jìn)程 | TCP協(xié)議通訊流程

    「網(wǎng)絡(luò)編程」第二講:socket套接字(四 - 完結(jié))_ Linux任務(wù)管理與守護(hù)進(jìn)程 | TCP協(xié)議通訊流程

    「前言」文章是關(guān)于網(wǎng)絡(luò)編程的socket套接字方面的,上一篇是網(wǎng)絡(luò)編程socket套接字(三),這篇續(xù)上篇文章的內(nèi)容,下面開(kāi)始講解!? 「歸屬專欄」網(wǎng)絡(luò)編程 「主頁(yè)鏈接」個(gè)人主頁(yè) 「筆者」楓葉先生(fy) 「楓葉先生有點(diǎn)文青病」「句子分享」 Time?goes?on?and?on,?never?to?an?

    2024年02月10日
    瀏覽(47)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包