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

linux【網(wǎng)絡編程】之UDP網(wǎng)絡程序模擬實現(xiàn)

這篇具有很好參考價值的文章主要介紹了linux【網(wǎng)絡編程】之UDP網(wǎng)絡程序模擬實現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、開發(fā)環(huán)境

本次實驗是在騰訊云服務器上進行

二、服務端實現(xiàn)

做完這次實驗,感受最深的就是函數(shù)接口方面的問題,我們先來介紹一下需要用到的接口。

2.1 接口認識

2.1.1 socket創(chuàng)建網(wǎng)絡通信套接字


#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

參數(shù)domain:域,未來套接字是進行網(wǎng)絡通信(AF_INET)還是本地通信(AF_UNIX, AF_LOCAL)

參數(shù)type:套接字提供服務的類型,如SOCK_STREAM:流式服務TCP策略,SOCK_DGRAM:數(shù)據(jù)報服務,UDP策略

參數(shù)protocol:缺省為0,可由前兩個類型確定

返回值:失敗返回-1,成功返回文件描述符

2.1.2 bind:綁定Ip和端口號

綁定端口號和ip
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

參數(shù)sockfd:文件描述符,也就是調(diào)用socket的返回值

參數(shù)addr:利用struct sockaddr_in強轉(zhuǎn)

參數(shù)addrlen:結(jié)構(gòu)體的大小

返回值:成功返回0,失敗返回-1

2.1.3 sockaddr_in結(jié)構(gòu)體

struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);//協(xié)議家族,對應AF_INET
    in_port_t sin_port;		//端口號,in_port_t是對port的重命名
    struct in_addr sin_addr;//IP地址,in_addr結(jié)構(gòu)體里封裝了一個32位整數(shù)

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];
  };

#define	__SOCKADDR_COMMON(sa_prefix) \
  sa_family_t sa_prefix##family
//sa_family_t //16位整數(shù)

typedef uint16_t in_port_t;

typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };

宏中的**##**是將兩個字符串合并成一個新字符串,也就是將接收到的sa_prefix與family合并起來,形成了sa_prefix_family

創(chuàng)建結(jié)構(gòu)體后要先清空數(shù)據(jù)

#include <strings.h>
void bzero(void *s, size_t n);

2.1.4 IP地址轉(zhuǎn)換函數(shù):inet_addr、inet_ntoa

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
inet_addr內(nèi)部完成兩件事情:1.把字符串轉(zhuǎn)化成整數(shù);2.再把整數(shù)轉(zhuǎn)化成對應的網(wǎng)絡序列**
in_addr_t inet_addr(const char *cp);
//const char*cp:點分十進制風格的IP地址

//1.網(wǎng)絡->主機 2.uint32_t -> 點分十進制
char *inet_ntoa(struct in_addr in);

2.1.5 recvfrom:讀取數(shù)據(jù)

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

sockfd:特定的套接字,buf:讀取到特定緩沖區(qū),len:結(jié)構(gòu)體大小
flags:讀取的方式,默認為0,阻塞讀取
src_addr:輸入輸出型參數(shù),收到消息除了本身,還得知道是那個IP+port發(fā)過來的數(shù)據(jù)
len:大小是多少
返回-1表示失敗,成功返回字節(jié)數(shù)

2.2 頭文件udpServer.hpp

頭文件中:構(gòu)造負責初始化參數(shù)
initServer函數(shù)負責初始化服務器:1.創(chuàng)建套接字;2.將套接字與IP地址和端口號綁定。
start()函數(shù)服務器本質(zhì)是一個死循環(huán),在start啟動的時候,通過recvfrom讀取通過網(wǎng)絡發(fā)來的數(shù)據(jù)、源ip+源端口號分別保存到緩沖區(qū)和struct sockaddr這個結(jié)構(gòu)體中

#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <functional>
namespace Server
{
    using namespace std;

    //默認的點分十進制IP
    static const string defaultIP="0.0.0.0";
    static const int gnum=1024;//緩沖區(qū)大小
    
    enum{USAGE_ERR=1,SOCKET_ERR,BIND_ERR};//退出碼

    typedef function<void(string,uint16_t,string)> func_t;

    class udpServer
    {
    public:
        udpServer(const func_t& callback,const uint16_t &port,const string& ip=defaultIP)
            :callback_(callback),port_(port),ip_(ip),sockfd_(-1)
        {}
        void initServer()
        {
            //****創(chuàng)建UDP網(wǎng)絡通信端口****
            sockfd_=socket(AF_INET,SOCK_DGRAM,0);
            if(sockfd_==-1)
            {
                cerr << "socket error: " << errno << " : " << strerror(errno) << endl;
                exit(SOCKET_ERR);
            }
            cout << "socket success: " << " : " << sockfd_ << endl;

            //******綁定port,ip****
            //服務器要明確綁定port,不能隨意改變,需要程序員顯示指明
            struct sockaddr_in local;
            bzero(&local,sizeof(local));//對結(jié)構(gòu)體數(shù)據(jù)清0

            //填充結(jié)構(gòu)體

            local.sin_family=AF_INET;
            //大小端轉(zhuǎn)換,給別人發(fā)消息,端口號和IP地址也要發(fā)給對方
            local.sin_port=htons(port_);//端口號轉(zhuǎn)網(wǎng)絡

            //1.string->uint32_t  2.htonl()---->兩個工作統(tǒng)一交給inet_addr
            local.sin_addr.s_addr=inet_addr(ip_.c_str());//ip轉(zhuǎn)網(wǎng)絡
            // local.sin_addr.s_addr=htonl(INADDR_ANY);//任意地址綁定,服務器真正寫法,上面與這個選一個就行

            int n=bind(sockfd_,(struct sockaddr*)&local,sizeof(local));
            if(n==-1)
            {
                cerr << "bind error: " << errno << " : " << strerror(errno) << endl;
                exit(BIND_ERR);
            }
        }
        void start()
        {
            char buffer[gnum];
            for(;;)
            {
                //****讀取數(shù)據(jù)****

                //服務器的本質(zhì)就是一個死循環(huán)
                struct sockaddr_in peer;//做輸入輸出型參數(shù)
                socklen_t len=sizeof(peer);//必填
                //數(shù)據(jù)獲?。篒P地址+端口號+數(shù)據(jù)
                ssize_t s= recvfrom(sockfd_,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
                if(s>0)
                {
                    buffer[s]=0;
                    //1.網(wǎng)絡->主機 2.uint32_t -> 點分十進制
                    //string clientip=peer.sin_addr.s_addr;需要轉(zhuǎn)兩步,不方便 
                    string clientip=inet_ntoa(peer.sin_addr);
                    uint16_t clientport=ntohs(peer.sin_port);
                    string message=buffer;

                    cout<<clientip<<"["<<clientport<<"]#"<<message<<endl;
                    //利用回調(diào)方法處理數(shù)據(jù),實現(xiàn)解耦
                    callback_(clientip,clientport,message);
                }
            }
        }

        ~udpServer(){}
    private:
        uint16_t port_;//端口號
        string ip_;//IP地址
        int sockfd_;//文件描述符
        func_t callback_;//回調(diào)
    };
}

2.3 綁定IP和port問題

  • 一般情況下,服務器不會綁定某一個確定的IP,避免因綁定一個確定的
    IP而漏掉另一個ip發(fā)過來的數(shù)據(jù),實際情況是,將ip設(shè)置為全0,任何提交到服務器的開放端口的數(shù)據(jù)都會被該服務器處理
  • 服務器不需要綁定一個固定IP(目的ip有多個,可能是本地環(huán)回、內(nèi)網(wǎng)IP、公網(wǎng)IP),只要是訪問服務器上的某個開放的端口,都會把數(shù)據(jù)拿過來處理,但這并不意味著客戶端不需要綁定IP
  • 這個IP是目的IP,是已經(jīng)收到了數(shù)據(jù)向上交付的時候,不需要綁定IP,只需要看端口號就行了

linux【網(wǎng)絡編程】之UDP網(wǎng)絡程序模擬實現(xiàn)
本地環(huán)回:客戶端與服務端在一臺主機上,進行通信的時候數(shù)據(jù)貫穿協(xié)議棧流動,但不會到達物理層(出不去),僅測試
linux【網(wǎng)絡編程】之UDP網(wǎng)絡程序模擬實現(xiàn)
內(nèi)網(wǎng)IP:真正屬于這個服務器的IP,同一個品牌的服務器可以用內(nèi)網(wǎng)ip通信
公網(wǎng)IP:云服務器是虛擬的,不能直接bind公網(wǎng)IP
虛擬機或者真正的linux可以綁定
內(nèi)網(wǎng)IP可以被綁定

2.4 源文件udpServer.cc

服務器端進行測試的時候不需要提供IP地址

#include "udpServer.hpp"

#include <memory>
using namespace std;
using namespace Server;

static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}

void handlerMessage(string,uint16_t,string)
{
    //對message進行處理,完成server通信與業(yè)務邏輯解耦
}

int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port=atoi(argv[1]);
    std::unique_ptr<udpServer> usvr(new udpServer(handlerMessage,port));
    usvr->initServer();
    usvr->start();

    return 0;
}

三、客戶端實現(xiàn)

3.1 接口認識

3.1.1 數(shù)據(jù)發(fā)送:sendto

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
sockfd:發(fā)送給哪個套接字,
buf:要發(fā)送的消息;len:消息的字節(jié)數(shù);flags:0,有數(shù)據(jù)就發(fā),沒數(shù)據(jù)就阻塞
dest_addr:這個結(jié)構(gòu)體也是由struct sockaddr_in強轉(zhuǎn),指明向誰發(fā),填充服務器的IP和端口
addrlen:輸入型參數(shù)

3.2 頭文件udpClient.hpp

在這個文件中:構(gòu)造函數(shù)負責初始化變量

initClient函數(shù)負責創(chuàng)建套接字但是不需要程序員手動綁定端口號,OS會幫我們綁
服務端明確綁定是因為需要客戶端知道,并且不能隨便改變;未來是多個客戶端訪問一個服務端,客戶端端口號是多少不重要,保證唯一性就行

run()函數(shù)負責發(fā)送數(shù)據(jù)到服務端,需要用到sendto函數(shù),而sendto函數(shù)在首次發(fā)送數(shù)據(jù)的時候,OS發(fā)現(xiàn)客戶端還未綁定端口號,會令sendto函數(shù)自動綁定一個端口號

#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
namespace Client
{
    using namespace std;

    // //默認的點分十進制IP
    // static const string defaultIP="0.0.0.0";
    // static const int gnum=1024;
    
    enum{USAGE_ERR=1,SOCKET_ERR,BIND_ERR};//退出碼

    class udpClient
    {
    public:
        udpClient(const string& serverip,const uint16_t&serverport)
            :serverip_(serverip),serverport_(serverport),sockfd_(-1),quit_(false)
        {}
        void initClient()
        {
            //****1.創(chuàng)建UDP網(wǎng)絡通信端口****
            sockfd_=socket(AF_INET,SOCK_DGRAM,0);
            if(sockfd_==-1)
            {
                cerr << "socket error: " << errno << " : " << strerror(errno) << endl;
                exit(SOCKET_ERR);
            }
            cout << "socket success: " << " : " << sockfd_ << endl;

            //****Client必須要bind,但是Client不需要顯示bind(不需要自己寫)******/
            //客戶端端口是多少不重要,只要能保證唯一性就行,讓OS自己去綁
        }

        void run()
        {
            /*********發(fā)送數(shù)據(jù)***********/
            struct sockaddr_in server;
            memset(&server,0,sizeof(server));
            server.sin_family=AF_INET;
            //主機序列轉(zhuǎn)網(wǎng)絡序列
            server.sin_addr.s_addr=inet_addr(serverip_.c_str());
            server.sin_port=htons(serverport_);

            string message;
            while (!quit_) 
            {
                cout<<"Please Enter# "<<endl;
                cin>>message;
                //首次向服務器發(fā)送數(shù)據(jù)的時候,OS識別到還未綁定,sendto自動綁定ip+port
                sendto(sockfd_,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));
            }
            
        }

        ~udpClient()
        {}
    private:
        int sockfd_;
        string serverip_;
        uint16_t serverport_;
        bool quit_;
    };
}

3.3 源文件udpClient.cc

客戶端進行測試的時候必須要提供IP地址和端口號

#include "udpClient.hpp"
#include <memory>
using namespace std;
using namespace Client;

static void Usage(string proc)
{
    cout << "\nUsage:\n\t" <<proc << " server_ip server_port\n\n";
}

//udpClient server_ip server_port
int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }

    //客戶端必須要知道發(fā)給誰
    string serverip=argv[1];
    uint16_t serverport=atoi(argv[2]);

    unique_ptr<udpClient> ucli(new udpClient(serverip,serverport));
    ucli->initClient();
    ucli->run();

    return 0;
}

四、結(jié)果展示

linux【網(wǎng)絡編程】之UDP網(wǎng)絡程序模擬實現(xiàn)

無論是客戶端還是服務端的測試文件,所要傳遞的參數(shù)(ip、port)與頭文件中struct sockaddr_in需要填充的ip、port沒有關(guān)系

這篇博客只是講解一下UDP下網(wǎng)絡通信的邏輯,關(guān)于它的應用方面會在近期推出,敬請關(guān)注!!!文章來源地址http://www.zghlxwxcb.cn/news/detail-438614.html

到了這里,關(guān)于linux【網(wǎng)絡編程】之UDP網(wǎng)絡程序模擬實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • 【網(wǎng)絡編程】基于UDP數(shù)據(jù)報實現(xiàn)回顯服務器/客戶端程序

    【網(wǎng)絡編程】基于UDP數(shù)據(jù)報實現(xiàn)回顯服務器/客戶端程序

    個人主頁:兜里有顆棉花糖 歡迎 點贊?? 收藏? 留言? 加關(guān)注??本文由 兜里有顆棉花糖 原創(chuàng) 收錄于專欄【網(wǎng)絡編程】【Java系列】 本專欄旨在分享學習網(wǎng)絡編程的一點學習心得,歡迎大家在評論區(qū)交流討論?? 前言 我們?nèi)绻胱寫贸绦蜻M行網(wǎng)絡通信的話,就需要調(diào)用傳

    2024年02月04日
    瀏覽(28)
  • 【計算機網(wǎng)絡】網(wǎng)絡編程套接字&UDP服務器客戶端的簡單模擬

    【計算機網(wǎng)絡】網(wǎng)絡編程套接字&UDP服務器客戶端的簡單模擬

    需要云服務器等云產(chǎn)品來學習Linux的同學可以移步/–騰訊云–/官網(wǎng),輕量型云服務器低至112元/年,優(yōu)惠多多。(聯(lián)系我有折扣哦) 每臺主機都有自己的IP地址,當數(shù)據(jù)在進行通信的時候,除了要發(fā)送的數(shù)據(jù)外,在報頭里面還要包含發(fā)送方的IP和接收方的IP,這里發(fā)送方的IP就

    2024年02月20日
    瀏覽(101)
  • Linux網(wǎng)絡編程——UDP編程

    Linux網(wǎng)絡編程——UDP編程

    1、UDP通信協(xié)議,服務器端和客戶端無需建立連接,只需要知道對方套接字的地址信息就可以發(fā)送數(shù)據(jù) 2、UDP通信流程圖: 功能:創(chuàng)建套接字并返回套接字描述符 功能:將套接字與IP地址和端口號綁定 功能:發(fā)送數(shù)據(jù) 功能:接收數(shù)據(jù) 功能:關(guān)閉套接字 1、代碼功能:兩個進程

    2023年04月19日
    瀏覽(24)
  • 【Linux C | 網(wǎng)絡編程】多播的概念、多播地址、UDP實現(xiàn)多播的C語言例子

    【Linux C | 網(wǎng)絡編程】多播的概念、多播地址、UDP實現(xiàn)多播的C語言例子

    ??博客主頁??:??https://blog.csdn.net/wkd_007?? ??博客內(nèi)容??:??嵌入式開發(fā)、Linux、C語言、C++、數(shù)據(jù)結(jié)構(gòu)、音視頻?? ??本文內(nèi)容??:??介紹多播的概念、多播地址、UDP實現(xiàn)廣播的C語言例子 ?? ??金句分享??:??你不能選擇最好的,但最好的會來選擇你——泰戈爾??

    2024年03月11日
    瀏覽(20)
  • Linux C程序開發(fā),多線程編程、網(wǎng)絡編程

    Linux C程序開發(fā),多線程編程、網(wǎng)絡編程

    目錄 多線程編程 網(wǎng)絡編程 Linux C程序開發(fā)是指在Linux操作系統(tǒng)下使用C語言進行開發(fā)的過程。Linux是一種開源的操作系統(tǒng),具有穩(wěn)定性、安全性和靈活性等優(yōu)點,因此在很多領(lǐng)域都得到了廣泛的應用。 多線程編程是指在一個程序中同時運行多個線程,每個線程都有自己的執(zhí)行路

    2024年02月13日
    瀏覽(27)
  • Linux網(wǎng)絡編程(四)——UDP通信

    Linux網(wǎng)絡編程(四)——UDP通信

    目錄 0x01 UDP協(xié)議 一、UDP通信簡介以及接口 二、UDP的接口 三、UDP收發(fā)例程 0x02 廣播 一、設(shè)置廣播數(shù)據(jù)函數(shù)接口 二、廣播代碼實現(xiàn) 0x03 組播(多播) 一、組播地址 二、設(shè)置組播函數(shù)接口 三、代碼實現(xiàn) UDP是一個面向無連接的,不可靠的服務,功能即為在IP的數(shù)據(jù)報服務之上增

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

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

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

    2024年02月08日
    瀏覽(89)
  • 【Linux網(wǎng)絡】網(wǎng)絡編程套接字(預備知識+UDP)

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

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

    2024年02月19日
    瀏覽(93)
  • 【socket】從計算機網(wǎng)絡基礎(chǔ)到socket編程——Windows && Linux C語言 + Python實現(xiàn)(TCP+UDP)

    【socket】從計算機網(wǎng)絡基礎(chǔ)到socket編程——Windows && Linux C語言 + Python實現(xiàn)(TCP+UDP)

    簡單講一下基礎(chǔ)知識,便于后面代碼的理解,建議大概瀏覽一下這一小節(jié)內(nèi)容。這里講的只是冰山一角,建議大家學習計算機網(wǎng)絡相關(guān)知識,推薦幾本書: 《計算機網(wǎng)絡》(謝希仁) 《計算機網(wǎng)絡 自頂向下方法》 《計算機網(wǎng)絡技術(shù)》 《計算機網(wǎng)絡基礎(chǔ)及應用》 《Linux C從入

    2024年02月08日
    瀏覽(22)
  • Linux網(wǎng)絡編程系列之UDP組播

    Linux網(wǎng)絡編程系列之UDP組播

    ? ? ? ? 1、 Linux網(wǎng)絡編程系列之網(wǎng)絡編程基礎(chǔ) ? ? ? ? 2、 Linux網(wǎng)絡編程系列之TCP協(xié)議編程 ? ? ? ? 3、 Linux網(wǎng)絡編程系列之UDP協(xié)議編程 ? ? ? ? 4、 Linux網(wǎng)絡編程系列之UDP廣播 ? ? ? ? 5、 Linux網(wǎng)絡編程系列之UDP組播 ? ? ? ? 6、 Linux網(wǎng)絡編程系列之服務器編程——阻塞IO模型

    2024年02月04日
    瀏覽(23)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包