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

【探索Linux】P.28(網(wǎng)絡(luò)編程套接字 —— 簡單的UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn))

這篇具有很好參考價(jià)值的文章主要介紹了【探索Linux】P.28(網(wǎng)絡(luò)編程套接字 —— 簡單的UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn))。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

【探索Linux】P.28(網(wǎng)絡(luò)編程套接字 —— 簡單的UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn)),Linux,網(wǎng)絡(luò),linux,udp

引言

在前一篇文章中,我們詳細(xì)介紹了UDP協(xié)議和TCP協(xié)議的特點(diǎn)以及它們之間的異同點(diǎn)。本文將延續(xù)上文內(nèi)容,重點(diǎn)討論簡單的UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn)。通過本文的學(xué)習(xí),讀者將能夠深入了解UDP協(xié)議的實(shí)際應(yīng)用,并掌握如何編寫簡單的UDP網(wǎng)絡(luò)程序。讓我們一起深入探討UDP網(wǎng)絡(luò)程序的實(shí)現(xiàn)細(xì)節(jié),為網(wǎng)絡(luò)編程的學(xué)習(xí)之旅添上一份精彩的實(shí)踐經(jīng)驗(yàn)。

一、UDP協(xié)議

UDP(User Datagram Protocol)是一種無連接的、輕量級的網(wǎng)絡(luò)傳輸協(xié)議,它提供了快速、簡單的數(shù)據(jù)傳輸服務(wù)。下面是一個(gè)簡單的UDP程序?qū)崿F(xiàn)示例,包括一個(gè)UDP服務(wù)器和一個(gè)UDP客戶端。詳介紹可以看上一篇文章:UDP協(xié)議介紹 | TCP協(xié)議介紹 | UDP 和 TCP 的異同

二、UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn)

1. 預(yù)備代碼

?makefile文件

.PHONY:all
all:udpserver udpclient

udpserver:Main.cc
	g++ -o $@ $^ -std=c++11
udpclient:UdpClient.cc
	g++ -o $@ $^ -lpthread -std=c++11


.PHONY:clean
clean:
	rm -f udpserver udpclient

這段代碼是一個(gè)簡單的 Makefile 文件,用于編譯 UDP 服務(wù)器(udpserver)和 UDP 客戶端(udpclient)的程序。在這個(gè) Makefile 中定義了兩個(gè)規(guī)則:

  1. all:表示默認(rèn)的目標(biāo),依賴于 udpserver 和 udpclient 目標(biāo),即執(zhí)行 make 命令時(shí)會編譯 udpserver 和 udpclient。
  2. clean:用于清理生成的可執(zhí)行文件 udpserver 和 udpclient。

在 Makefile 中使用了一些特殊的關(guān)鍵字和變量:

  • .PHONY:聲明 all 和 clean 是偽目標(biāo),不是真正的文件名。
  • $@:表示目標(biāo)文件名。
  • $^:表示所有依賴文件列表。
  • -std=c++11:指定 C++ 的編譯標(biāo)準(zhǔn)為 C++11。
  • -lpthread:鏈接 pthread 庫,用于多線程支持。

?打印日志文件

#pragma once

#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define SIZE 1024

#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

#define Screen 1
#define Onefile 2
#define Classfile 3

#define LogFile "log.txt"

class Log
{
public:
    Log()
    {
        printMethod = Screen; // 默認(rèn)輸出方式為屏幕打印
        path = "./log/"; // 默認(rèn)日志文件存放路徑
    }

    void Enable(int method)
    {
        printMethod = method; // 設(shè)置日志輸出方式(屏幕、單個(gè)文件、分類文件)
    }

    std::string levelToString(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "None";
        }
    }

    void printLog(int level, const std::string &logtxt)
    {
        switch (printMethod)
        {
        case Screen:
            std::cout << logtxt << std::endl; // 屏幕打印日志信息
            break;
        case Onefile:
            printOneFile(LogFile, logtxt); // 將日志信息追加寫入單個(gè)文件
            break;
        case Classfile:
            printClassFile(level, logtxt); // 將日志信息追加寫入分類文件
            break;
        default:
            break;
        }
    }

    void printOneFile(const std::string &logname, const std::string &logtxt)
    {
        std::string _logname = path + logname; // 構(gòu)建日志文件的完整路徑
        int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // 打開文件,如果文件不存在則創(chuàng)建
        if (fd < 0)
            return;
        write(fd, logtxt.c_str(), logtxt.size()); // 將日志信息寫入文件
        close(fd);
    }

    void printClassFile(int level, const std::string &logtxt)
    {
        std::string filename = LogFile;
        filename += ".";
        filename += levelToString(level); // 構(gòu)建分類文件名,例如"log.txt.Debug/Warning/Fatal"
        printOneFile(filename, logtxt); // 將日志信息追加寫入分類文件
    }

    ~Log()
    {
    }

    void operator()(int level, const char *format, ...)
    {
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        char leftbuffer[SIZE];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                 ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        // 格式:默認(rèn)部分+自定義部分
        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);

        printLog(level, logtxt); // 打印日志信息
    }

private:
    int printMethod; // 日志輸出方式
    std::string path; // 日志文件存放路徑
};

該代碼實(shí)現(xiàn)了一個(gè)簡單的日志記錄類(Log),其中包括設(shè)置日志輸出方式(屏幕、單個(gè)文件、分類文件)和打印日志信息的功能。

  • Log 類是一個(gè)用于記錄日志的類。
  • Enable 函數(shù)用于設(shè)置日志輸出方式,可以選擇屏幕打印、單個(gè)文件或分類文件。
  • printLog 函數(shù)根據(jù)設(shè)置的日志輸出方式,將日志信息打印到屏幕、追加寫入單個(gè)文件或分類文件。
  • printOneFile 函數(shù)用于將日志信息追加寫入單個(gè)文件。
  • printClassFile 函數(shù)用于將日志信息追加寫入分類文件。
  • levelToString 函數(shù)將日志級別轉(zhuǎn)換為對應(yīng)的字符串表示。
  • operator() 函數(shù)是重載的函數(shù)調(diào)用運(yùn)算符,用于打印日志信息。
  • path 是日志文件存放路徑,默認(rèn)為"./log/"。
  • printMethod 是日志輸出方式,默認(rèn)為屏幕打印。
  • SIZE 定義了緩沖區(qū)大小。
  • Info、DebugWarning、ErrorFatal 是日志級別的定義。
  • Screen、OnefileClassfile 是日志輸出方式的定義。
  • LogFile 是單個(gè)文件名的定義。

?打開指定的終端設(shè)備文件,并將其作為標(biāo)準(zhǔn)錯(cuò)誤輸出的目標(biāo)文件描述符

#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 定義要打開的終端設(shè)備文件路徑
std::string terminal = "/dev/pts/6";

// 打開指定的終端設(shè)備文件,并將其作為標(biāo)準(zhǔn)錯(cuò)誤輸出的目標(biāo)文件描述符
int OpenTerminal()
{
    // 使用open函數(shù)以只寫方式打開終端設(shè)備文件
    int fd = open(terminal.c_str(), O_WRONLY);
    if(fd < 0)
    {
        // 如果打開終端設(shè)備文件失敗,則輸出錯(cuò)誤信息到標(biāo)準(zhǔn)錯(cuò)誤輸出
        std::cerr << "open terminal error" << std::endl;
        return 1; // 返回錯(cuò)誤代碼
    }

    // 將終端設(shè)備文件的文件描述符復(fù)制給標(biāo)準(zhǔn)錯(cuò)誤輸出的文件描述符
    // 這樣標(biāo)準(zhǔn)錯(cuò)誤輸出就會重定向到指定的終端設(shè)備上
    dup2(fd, 2);

    // 如果需要在此處輸出信息到標(biāo)準(zhǔn)錯(cuò)誤輸出,可以使用printf等函數(shù)

    // 關(guān)閉文件描述符
    // close(fd);

    return 0; // 返回成功代碼
}

這段代碼的作用是打開一個(gè)終端設(shè)備文件 “/dev/pts/6”,將其作為標(biāo)準(zhǔn)錯(cuò)誤輸出(stderr)的目標(biāo)文件描述符,實(shí)現(xiàn)將錯(cuò)誤信息輸出到指定的終端設(shè)備上。

  • terminal 變量存儲了要打開的終端設(shè)備文件路徑 “/dev/pts/6”。
  • OpenTerminal 函數(shù)嘗試打開指定的終端設(shè)備文件,并將其作為標(biāo)準(zhǔn)錯(cuò)誤輸出的目標(biāo)文件描述符。
    • 首先使用 open 函數(shù)打開終端設(shè)備文件,以只寫方式(O_WRONLY)。
    • 如果成功打開終端設(shè)備文件,則將其文件描述符復(fù)制給標(biāo)準(zhǔn)錯(cuò)誤輸出的文件描述符(2),即 dup2(fd, 2),這樣標(biāo)準(zhǔn)錯(cuò)誤輸出就會重定向到該終端設(shè)備上。
    • 如果打開終端設(shè)備文件失敗,則輸出錯(cuò)誤信息到標(biāo)準(zhǔn)錯(cuò)誤輸出,并返回錯(cuò)誤代碼 1。
    • 最后函數(shù)返回0表示成功。

2. UDP 服務(wù)器端實(shí)現(xiàn)(UdpServer.hpp)

#pragma once

#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include <unordered_map>
#include "Log.hpp"

// 使用Log類記錄日志信息
Log lg;

enum {
    SOCKET_ERR = 1,
    BIND_ERR
};

uint16_t defaultport = 8080;
std::string defaultip = "0.0.0.0";
const int size = 1024;

class UdpServer {
public:
    UdpServer(const uint16_t& port = defaultport, const std::string& ip = defaultip)
        : sockfd_(0), port_(port), ip_(ip), isrunning_(false)
    {}

    void Init() {
        // 1. 創(chuàng)建UDP socket
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); // PF_INET
        if (sockfd_ < 0) {
            lg(Fatal, "socket create error, sockfd: %d", sockfd_);
            exit(SOCKET_ERR);
        }
        lg(Info, "socket create success, sockfd: %d", sockfd_);

        // 2. 綁定socket
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_); // 端口號需要轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序
        local.sin_addr.s_addr = inet_addr(ip_.c_str()); // 將IP地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序

        if (bind(sockfd_, (const struct sockaddr*)&local, sizeof(local)) < 0) {
            lg(Fatal, "bind error, errno: %d, err string: %s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(Info, "bind success, errno: %d, err string: %s", errno, strerror(errno));
    }

    void CheckUser(const struct sockaddr_in& client, const std::string clientip, uint16_t clientport) {
        // 檢查用戶是否已經(jīng)存在在線用戶列表中
        auto iter = online_user_.find(clientip);
        if (iter == online_user_.end()) {
            online_user_.insert({clientip, client});
            std::cout << "[" << clientip << ":" << clientport << "] add to online user." << std::endl;
        }
    }

    void Broadcast(const std::string& info, const std::string clientip, uint16_t clientport) {
        // 廣播消息給所有在線用戶
        for (const auto& user : online_user_) {
            std::string message = "[";
            message += clientip;
            message += ":";
            message += std::to_string(clientport);
            message += "]# ";
            message += info;
            
            socklen_t len = sizeof(user.second);
            sendto(sockfd_, message.c_str(), message.size(), 0, (struct sockaddr*)(&user.second), len);
        }
    }

    void Run() {
        isrunning_ = true;
        char inbuffer[size];
        while (isrunning_) {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);

            // 接收客戶端發(fā)送的消息
            ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&client, &len);
            if (n < 0) {
                lg(Warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));
                continue;
            }

            // 獲取客戶端的IP地址和端口號
            uint16_t clientport = ntohs(client.sin_port);
            std::string clientip = inet_ntoa(client.sin_addr);

            // 檢查用戶是否已經(jīng)存在在線用戶列表中
            CheckUser(client, clientip, clientport);

            std::string info = inbuffer;

            // 將接收到的消息廣播給所有在線用戶
            Broadcast(info, clientip, clientport);
        }
    }

    ~UdpServer() {
        if (sockfd_ > 0)
            close(sockfd_);
    }

private:
    int sockfd_; // 網(wǎng)絡(luò)文件描述符
    std::string ip_; // 服務(wù)器IP地址
    uint16_t port_; // 服務(wù)器端口號
    bool isrunning_; // 服務(wù)器運(yùn)行狀態(tài)
    std::unordered_map<std::string, struct sockaddr_in> online_user_; // 在線用戶列表
};
  • Log.hpp 是用于記錄日志信息的頭文件。
  • lg 是一個(gè) Log 類的對象,用于輸出日志信息。
  • enum 定義了兩個(gè)錯(cuò)誤類型:SOCKET_ERRBIND_ERR,分別表示 socket 創(chuàng)建錯(cuò)誤和綁定錯(cuò)誤。
  • defaultportdefaultip 分別設(shè)置默認(rèn)的端口號和 IP 地址。
  • size 定義接收緩沖區(qū)的大小為 1024 字節(jié)。
  • UdpServer 類封裝了一個(gè) UDP 服務(wù)器。
  • 構(gòu)造函數(shù) UdpServer 接受端口號和 IP 地址作為參數(shù),并初始化成員變量。
  • Init 函數(shù)用于初始化 UDP 服務(wù)器,其中:
    • 創(chuàng)建 UDP socket,并檢查創(chuàng)建是否成功。
    • 綁定 socket 到指定的 IP 地址和端口號,并檢查綁定是否成功。
  • CheckUser 函數(shù)用于檢查用戶是否已經(jīng)存在在線用戶列表中,如果不存在則將其添加到列表中。
  • Broadcast 函數(shù)用于向所有在線用戶廣播消息,其中:
    • 消息格式為 [發(fā)送者IP:發(fā)送者端口號]# 消息內(nèi)容。
    • 使用 sendto 函數(shù)發(fā)送消息給每個(gè)在線用戶。
  • Run 函數(shù)是 UDP 服務(wù)器的主循環(huán),其中:
    • 循環(huán)接收客戶端發(fā)送的消息,并將其廣播給所有在線用戶。
    • 對每個(gè)客戶端,獲取其 IP 地址和端口號,并進(jìn)行用戶檢查和消息廣播。
  • ~UdpServer 析構(gòu)函數(shù)關(guān)閉網(wǎng)絡(luò)文件描述符。
  • sockfd_ 是網(wǎng)絡(luò)文件描述符,用于創(chuàng)建和管理網(wǎng)絡(luò)連接。
  • ip_ 是服務(wù)器的 IP 地址。
  • port_ 是服務(wù)器的端口號。
  • isrunning_ 表示服務(wù)器的運(yùn)行狀態(tài),用于控制循環(huán)退出。
  • online_user_ 是一個(gè)無序映射,用于保存在線用戶的 IP 地址和對應(yīng)的 sockaddr_in 結(jié)構(gòu)體。

3. UDP 客戶端實(shí)現(xiàn)(main函數(shù))

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "Terminal.hpp"

using namespace std;

// 函數(shù)聲明:打印程序的使用方法
void Usage(std::string proc);

// 結(jié)構(gòu)體:用于傳遞線程參數(shù)
struct ThreadData
{
    struct sockaddr_in server; // 服務(wù)器地址結(jié)構(gòu)體
    int sockfd; // socket 文件描述符
    std::string serverip; // 服務(wù)器 IP 地址
};

// 線程函數(shù):接收消息
void *recv_message(void *args);

// 線程函數(shù):發(fā)送消息
void *send_message(void *args);

// 主函數(shù)
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]); // 打印使用方法
        exit(0);
    }

    // 解析命令行參數(shù)
    std::string serverip = argv[1]; // 服務(wù)器 IP 地址
    uint16_t serverport = std::stoi(argv[2]); // 服務(wù)器端口號

    // 初始化 ThreadData 結(jié)構(gòu)體
    struct ThreadData td;
    bzero(&td.server, sizeof(td.server)); // 清零服務(wù)器地址結(jié)構(gòu)體
    td.server.sin_family = AF_INET; // 設(shè)置地址族為 IPv4
    td.server.sin_port = htons(serverport); // 設(shè)置端口號(轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序)
    td.server.sin_addr.s_addr = inet_addr(serverip.c_str()); // 設(shè)置服務(wù)器 IP 地址(轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序)

    // 創(chuàng)建 UDP socket
    td.sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (td.sockfd < 0)
    {
        cout << "socket error" << endl;
        return 1;
    }

    td.serverip = serverip; // 存儲服務(wù)器 IP 地址

    pthread_t recvr, sender; // 定義接收消息和發(fā)送消息的線程
    pthread_create(&recvr, nullptr, recv_message, &td); // 創(chuàng)建接收消息線程
    pthread_create(&sender, nullptr, send_message, &td); // 創(chuàng)建發(fā)送消息線程

    // 等待接收消息和發(fā)送消息的線程退出
    pthread_join(recvr, nullptr);
    pthread_join(sender, nullptr);

    close(td.sockfd); // 關(guān)閉 socket
    return 0;
}

// 函數(shù)實(shí)現(xiàn):打印程序的使用方法
void Usage(std::string proc)
{
    std::cout << "\n\rUsage: " << proc << " serverip serverport\n" << std::endl;
}

// 線程函數(shù)實(shí)現(xiàn):接收消息
void *recv_message(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args); // 強(qiáng)制類型轉(zhuǎn)換為 ThreadData 結(jié)構(gòu)體指針
    char buffer[1024]; // 接收消息的緩沖區(qū)
    while (true)
    {
        memset(buffer, 0, sizeof(buffer)); // 清空緩沖區(qū)
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);

        ssize_t s = recvfrom(td->sockfd, buffer, 1023, 0, (struct sockaddr *)&temp, &len); // 接收消息
        if (s > 0)
        {
            buffer[s] = 0;
            cerr << buffer << endl; // 輸出接收到的消息
        }
    }
}

// 線程函數(shù)實(shí)現(xiàn):發(fā)送消息
void *send_message(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args); // 強(qiáng)制類型轉(zhuǎn)換為 ThreadData 結(jié)構(gòu)體指針
    string message; // 存儲用戶輸入的消息
    socklen_t len = sizeof(td->server); // 服務(wù)器地址的長度

    // 發(fā)送歡迎消息
    std::string welcome = td->serverip + " comming...";
    sendto(td->sockfd, welcome.c_str(), welcome.size(), 0, (struct sockaddr *)&(td->server), len);

    while (true)
    {
        cout << "Please Enter@ ";
        getline(cin, message); // 獲取用戶輸入的消息

        sendto(td->sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&(td->server), len); // 發(fā)送消息給服務(wù)器
    }
}

溫馨提示

感謝您對博主文章的關(guān)注與支持!如果您喜歡這篇文章,可以點(diǎn)贊、評論和分享給您的同學(xué),這將對我提供巨大的鼓勵(lì)和支持。另外,我計(jì)劃在未來的更新中持續(xù)探討與本文相關(guān)的內(nèi)容。我會為您帶來更多關(guān)于Linux以及C++編程技術(shù)問題的深入解析、應(yīng)用案例和趣味玩法等。如果感興趣的話可以關(guān)注博主的更新,不要錯(cuò)過任何精彩內(nèi)容!

再次感謝您的支持和關(guān)注。我們期待與您建立更緊密的互動,共同探索Linux、C++、算法和編程的奧秘。祝您生活愉快,排便順暢!
【探索Linux】P.28(網(wǎng)絡(luò)編程套接字 —— 簡單的UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn)),Linux,網(wǎng)絡(luò),linux,udp文章來源地址http://www.zghlxwxcb.cn/news/detail-844587.html

到了這里,關(guān)于【探索Linux】P.28(網(wǎng)絡(luò)編程套接字 —— 簡單的UDP網(wǎng)絡(luò)程序模擬實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 【Linux網(wǎng)絡(luò)編程】網(wǎng)絡(luò)編程套接字二

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

    喜歡的點(diǎn)贊,收藏,關(guān)注一下把! TCP和UDP在編程接口上是非常像的,前面我們說過TCP是面向連接的,UDP我們上篇博客也寫過了,我們發(fā)現(xiàn)UDP服務(wù)端客戶端寫好啟動直接就發(fā)消息了沒有建立連接。TCP是建立連接的,注定在寫的時(shí)候肯定有寫不一樣的地方。具體怎么不一樣,我們

    2024年04月15日
    瀏覽(101)
  • linux【網(wǎng)絡(luò)編程】之網(wǎng)絡(luò)套接字預(yù)備

    linux【網(wǎng)絡(luò)編程】之網(wǎng)絡(luò)套接字預(yù)備

    在【網(wǎng)絡(luò)基礎(chǔ)】中我們提到了IP地址,接下來了解一下網(wǎng)絡(luò)通信中其他方面的知識 端口號是一個(gè)2字節(jié)16位的整數(shù); 端口號用來標(biāo)識一個(gè)進(jìn)程, 告訴操作系統(tǒng), 當(dāng)前的這個(gè)數(shù)據(jù)要交給哪一個(gè)進(jìn)程來處理; 一個(gè)端口號只能被一個(gè)進(jìn)程占用 通信原理 (公網(wǎng))IP唯一標(biāo)識一臺主機(jī),這樣兩臺

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

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

    目錄 地址轉(zhuǎn)換函數(shù) 字符串IP轉(zhuǎn)整數(shù)IP 整數(shù)IP轉(zhuǎn)字符串IP 關(guān)于inet_ntoa 簡單的單執(zhí)行流TCP網(wǎng)絡(luò)程序 TCP socket API 詳解及封裝TCP socket? 服務(wù)端創(chuàng)建套接字? 服務(wù)端綁定? 服務(wù)端監(jiān)聽? 服務(wù)端獲取連接? 服務(wù)端處理請求 客戶端創(chuàng)建套接字 客戶端連接服務(wù)器 客戶端發(fā)起請求 服務(wù)器測試

    2024年03月21日
    瀏覽(113)
  • Linux網(wǎng)絡(luò)編程(二-套接字)

    Linux網(wǎng)絡(luò)編程(二-套接字)

    目錄 一、背景知識 1.1 端口號 1.2 網(wǎng)絡(luò)字節(jié)序 1.3 地址轉(zhuǎn)換函數(shù)? 二、Socket簡介 三、套接字相關(guān)的函數(shù)? 3.1 socket() 3.2 bind() 3.3 connect() 3.4 listen() 3.5 accept()? 3.6 read()/recv()/recvfrom() 3.7 send()/sendto() ?3.8 close() ?四、UPD客服/服務(wù)端實(shí)驗(yàn)? 1.1 端口號 端口號是訪問服務(wù)器的標(biāo)識 ,就好像

    2024年01月22日
    瀏覽(166)
  • 【Linux】網(wǎng)絡(luò)編程套接字一

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

    上篇博客由唐僧的例子我們知道: 在IP數(shù)據(jù)包頭部中,有兩個(gè)IP地址,分別叫做源IP地址,和目的IP地址。 思考一下: 不考慮中間的一系列步驟,兩臺主機(jī)我們光有IP地址就可以完成通信了嘛? 想象一下發(fā)qq消息的例子,有了IP地址能夠把消息發(fā)送到對方的機(jī)器上。 但是我們把

    2024年03月26日
    瀏覽(1081)
  • 【Linux網(wǎng)絡(luò)編程】網(wǎng)絡(luò)編程套接字(TCP服務(wù)器)

    【Linux網(wǎng)絡(luò)編程】網(wǎng)絡(luò)編程套接字(TCP服務(wù)器)

    作者:愛寫代碼的剛子 時(shí)間:2024.4.4 前言:本篇博客主要介紹TCP及其服務(wù)器編碼 只介紹基于IPv4的socket網(wǎng)絡(luò)編程,sockaddr_in中的成員struct in_addr sin_addr表示32位 的IP地址 但是我們通常用點(diǎn)分十進(jìn)制的字符串表示IP地址,以下函數(shù)可以在字符串表示和in_addr表示之間轉(zhuǎn)換 字符串轉(zhuǎn)in

    2024年04月14日
    瀏覽(108)
  • Linux網(wǎng)絡(luò)編程——tcp套接字

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

    本章Gitee倉庫:tcp套接字 客戶端: 客戶端: 關(guān)于構(gòu)造和初始化,可以直接在構(gòu)造的時(shí)候,將服務(wù)器初始化,那為什么還要寫到 init 初始化函數(shù)里面呢? 構(gòu)造盡量簡單一點(diǎn),不要做一些“有風(fēng)險(xiǎn)”的操作。 tcp 是面向連接的,通信之前要建立連接,服務(wù)器處于等待連接到來的

    2024年02月20日
    瀏覽(96)
  • 【Linux】網(wǎng)絡(luò)基礎(chǔ)+UDP網(wǎng)絡(luò)套接字編程

    【Linux】網(wǎng)絡(luò)基礎(chǔ)+UDP網(wǎng)絡(luò)套接字編程

    只做自己喜歡做的事情,不被社會和時(shí)代裹挾著前進(jìn),是一件很奢侈的事。 1. 首先計(jì)算機(jī)是人類設(shè)計(jì)出來提高生產(chǎn)力的工具,而人類的文明綿延至今一定離不開人類之間互相的協(xié)作,既然人類需要協(xié)作以完成更為復(fù)雜的工作和難題,所以計(jì)算機(jī)作為人類的工具自然也一定需要

    2024年02月08日
    瀏覽(89)
  • 【Linux】網(wǎng)絡(luò)---->套接字編程(TCP)

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

    TCP的編程流程:大致可以分為五個(gè)過程,分別是準(zhǔn)備過程、連接建立過程、獲取新連接過程、消息收發(fā)過程和斷開過程。 1.準(zhǔn)備過程:服務(wù)端和客戶端需要?jiǎng)?chuàng)建各自的套接字,除此之外服務(wù)端還需要綁定自己的地址信息和進(jìn)行監(jiān)聽。注意:服務(wù)端調(diào)用listen函數(shù)后,處理監(jiān)聽狀

    2024年02月04日
    瀏覽(101)
  • 【Linux網(wǎng)絡(luò)】網(wǎng)絡(luò)編程套接字(預(yù)備知識+UDP)

    【Linux網(wǎng)絡(luò)】網(wǎng)絡(luò)編程套接字(預(yù)備知識+UDP)

    目錄 預(yù)備知識 1. 理解源IP地址和目的IP地址 2. 理解源MAC地址和目的MAC地址 3. 認(rèn)識端口號 ?4. 理解源端口號和目的端口號 5. 端口號(port) vs 進(jìn)程pid 6. 認(rèn)識TCP協(xié)議和認(rèn)識UDP協(xié)議 7. 網(wǎng)絡(luò)字節(jié)序 socket編程接口? 1. socket 常見API 2. sockaddr結(jié)構(gòu)? 簡單的UDP網(wǎng)絡(luò)程序? 1. 服務(wù)端創(chuàng)建udp

    2024年02月19日
    瀏覽(93)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包