国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

在哪里做網(wǎng)站比較好十大廣告投放平臺

在哪里做網(wǎng)站比較好,十大廣告投放平臺,wordpress調(diào)用最近文章,做深圳門戶網(wǎng)站起什么名字好?小白苦學(xué)IT的博客主頁 ?初學(xué)者必看:Linux操作系統(tǒng)入門 ?代碼倉庫:Linux代碼倉庫 ?關(guān)注我一起討論和學(xué)習(xí)Linux系統(tǒng) 1.前言 網(wǎng)絡(luò)編程前言 網(wǎng)絡(luò)編程是連接數(shù)字世界的橋梁,它讓計(jì)算機(jī)之間能夠交流信息,為我們的生活和工作帶來便利…

?小白苦學(xué)IT的博客主頁

?初學(xué)者必看:Linux操作系統(tǒng)入門

?代碼倉庫:Linux代碼倉庫

?關(guān)注我一起討論和學(xué)習(xí)Linux系統(tǒng)

1.前言

網(wǎng)絡(luò)編程前言

網(wǎng)絡(luò)編程是連接數(shù)字世界的橋梁,它讓計(jì)算機(jī)之間能夠交流信息,為我們的生活和工作帶來便利。從簡單的網(wǎng)頁瀏覽到復(fù)雜的分布式系統(tǒng),網(wǎng)絡(luò)編程無處不在。

然而,網(wǎng)絡(luò)編程涉及諸多復(fù)雜概念和技術(shù),如IP地址、端口號、Socket、TCP/UDP協(xié)議等,需要我們深入學(xué)習(xí)和掌握。同時(shí),網(wǎng)絡(luò)環(huán)境的復(fù)雜性、數(shù)據(jù)安全性等問題也帶來了挑戰(zhàn)。

但正是這些挑戰(zhàn),讓網(wǎng)絡(luò)編程充滿了無限可能。掌握網(wǎng)絡(luò)編程技術(shù),我們可以開發(fā)出各種創(chuàng)新應(yīng)用,為人們提供更高效、智能的服務(wù)。

本文旨在介紹網(wǎng)絡(luò)編程的Socket編程接口及其技術(shù),分享實(shí)用經(jīng)驗(yàn),幫助讀者打下堅(jiān)實(shí)的網(wǎng)絡(luò)編程基礎(chǔ)。

1.socket編程接口

socket常見API

// 創(chuàng)建 socket 文件描述符 (TCP/UDP, 客戶端 + 服務(wù)器)
int socket(int domain, int type, int protocol);
// 綁定端口號 (TCP/UDP, 服務(wù)器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
// 開始監(jiān)聽socket (TCP, 服務(wù)器)
int listen(int socket, int backlog);
// 接收請求 (TCP, 服務(wù)器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);
// 建立連接 (TCP, 客戶端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockaddr結(jié)構(gòu)

socket API是一層抽象的網(wǎng)絡(luò)編程接口,適用于各種底層網(wǎng)絡(luò)協(xié)議,如IPv4、IPv6,以及后面要談的UNIX DomainSocket. 然而, 各種網(wǎng)絡(luò)協(xié)議的地址格式并不相同.

  • IPv4和IPv6的地址格式定義在netinet/in.h中,IPv4地址用sockaddr_in結(jié)構(gòu)體表示,包括16位地址類型, 16位端口號和32位IP地址。
  • IPv4、IPv6地址類型分別定義為常數(shù)AF_INET、AF_INET6. 這樣,只要取得某種sockaddr結(jié)構(gòu)體的首地址,不需要知道具體是哪種類型的sockaddr結(jié)構(gòu)體,就可以根據(jù)地址類型字段確定結(jié)構(gòu)體中的內(nèi)容。
  • socket API可以都用struct sockaddr *類型表示, 在使用的時(shí)候需要強(qiáng)制轉(zhuǎn)化成sockaddr_in; 這樣的好處是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各種類型的sockaddr結(jié)構(gòu)體指針做為參數(shù)。

sockaddr 結(jié)構(gòu)?

sockaddr?是一個通用的套接字地址結(jié)構(gòu),它用于表示各種類型的套接字地址。但是,sockaddr?結(jié)構(gòu)本身并不包含足夠的信息來確定地址的類型,因此它通常被更具體的結(jié)構(gòu)(如?sockaddr_in)所替代。sockaddr?結(jié)構(gòu)的主要作用是為不同的地址結(jié)構(gòu)提供一個統(tǒng)一的接口。

  • 通用性sockaddr是一個通用的套接字地址結(jié)構(gòu),設(shè)計(jì)初衷是為了能夠表示各種類型的套接字地址,包括IPv4、IPv6以及其他可能的地址類型。這種通用性使得sockaddr能夠作為許多網(wǎng)絡(luò)編程函數(shù)的參數(shù),如bind、connectrecvfrom、sendto等,用于指明地址信息。
  • 擴(kuò)展性:通過定義sa_family字段,sockaddr能夠區(qū)分不同類型的地址結(jié)構(gòu)。這使得在未來引入新的地址類型時(shí),不需要修改現(xiàn)有函數(shù)的接口,只需定義新的地址結(jié)構(gòu)并設(shè)置相應(yīng)的sa_family即可。

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

sockaddr_in?是?sockaddr?結(jié)構(gòu)的一個特例,用于表示 IPv4 地址和端口號。它包含了 IP 地址和端口號的信息,以及地址族和協(xié)議信息。

  • IPv4特化:盡管sockaddr具有通用性,但在實(shí)際編程中,特別是在處理IPv4地址時(shí),直接使用sockaddr結(jié)構(gòu)會顯得過于復(fù)雜和冗余。sockaddr_in結(jié)構(gòu)是針對IPv4地址設(shè)計(jì)的,它包含了IPv4地址和端口號等必要信息,并且以更直觀和易于操作的方式呈現(xiàn)這些信息。
  • 便利性sockaddr_in提供了專門的字段來存儲IPv4地址(sin_addr)和端口號(sin_port),這使得在處理IPv4網(wǎng)絡(luò)編程任務(wù)時(shí)更加方便和高效。同時(shí),通過類型轉(zhuǎn)換,sockaddr_in結(jié)構(gòu)可以很容易地轉(zhuǎn)換為sockaddr結(jié)構(gòu),從而與需要sockaddr參數(shù)的函數(shù)兼容。

in_addr結(jié)構(gòu)?

in_addr?結(jié)構(gòu)用于表示一個 IPv4 地址。它通常與?sockaddr_in?結(jié)構(gòu)一起使用,作為?sin_addr?字段的類型。

在這個結(jié)構(gòu)中,s_addr?是一個無符號長整數(shù),表示 IPv4 地址。在實(shí)際使用中,我們通常不會直接操作這個長整數(shù),而是使用諸如?inet_pton?和?inet_ntop?這樣的函數(shù)來將點(diǎn)分十進(jìn)制格式的 IP 地址(如 "192.168.1.1")轉(zhuǎn)換為?in_addr?結(jié)構(gòu),或者將?in_addr?結(jié)構(gòu)轉(zhuǎn)換為點(diǎn)分十進(jìn)制格式的字符串。?

  • IPv4地址表示in_addr結(jié)構(gòu)專門用于表示IPv4地址。它通過一個無符號長整數(shù)(s_addr)來存儲IPv4地址,這種表示方式在網(wǎng)絡(luò)編程中非常常見。盡管IPv4地址通常以點(diǎn)分十進(jìn)制的形式表示(如192.168.1.1),但在內(nèi)部處理和網(wǎng)絡(luò)傳輸時(shí),它們通常被轉(zhuǎn)換為這種整數(shù)形式。
  • 轉(zhuǎn)換方便in_addr結(jié)構(gòu)使得在點(diǎn)分十進(jìn)制格式和內(nèi)部整數(shù)格式之間轉(zhuǎn)換IPv4地址變得相對簡單。通過調(diào)用如inet_ptoninet_ntop這樣的函數(shù),可以輕松實(shí)現(xiàn)這兩種格式之間的轉(zhuǎn)換,從而方便網(wǎng)絡(luò)編程中的地址處理。

總結(jié)一下就是:

  • sockaddr?是一個通用的套接字地址結(jié)構(gòu),用于表示各種類型的地址。
  • sockaddr_in?是?sockaddr?的一個特例,用于表示 IPv4 地址和端口號。
  • in_addr?用于表示 IPv4 地址。

這三種結(jié)構(gòu)的存在是為了滿足不同網(wǎng)絡(luò)編程需求和提高編程效率。sockaddr提供了通用性和擴(kuò)展性,sockaddr_in則針對IPv4地址提供了更直觀和便利的操作方式,而in_addr則專門用于表示和轉(zhuǎn)換IPv4地址。在實(shí)際編程中,根據(jù)具體需求選擇合適的結(jié)構(gòu)進(jìn)行處理,可以提高代碼的可讀性和可維護(hù)性。

2.簡單UDP的echo服務(wù)器(代碼實(shí)現(xiàn))

封裝 UdpSocket

UdpServer.hpp

默認(rèn)ip用 0.0.0.0

端口:8080

對udp服務(wù)器進(jìn)行封裝:

#pragma once
#include "Log.hpp"
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<errno.h>
#include<functional>using func_t = std::function<std::string (const std::string&,uint16_t &,const std::string&)>;uint16_t defaultport = 8080;
std::string defaultip = "0.0.0.0";
const int size = 1024;enum
{SOCKET_ERR = 1,BIND_ERR};class UdpServer
{
public:UdpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip):_sockfd(-1), _port(port), _ip(ip),_isrunning(false){}void Init(){//1.創(chuàng)建udp socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){log.LogMessage(FATAL, "socket create error,_sockfd: %d", _sockfd);exit(SOCKET_ERR);}log.LogMessage(INFO, "socket create success, _sockfd: %d ", _sockfd);//2.bind socketstruct sockaddr_in local;bzero(&local,sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);//需要保證我的端口號是網(wǎng)絡(luò)字節(jié)序列,因?yàn)樵摱丝谔柺且o對方發(fā)送的。local.sin_addr.s_addr = inet_addr(_ip.c_str()); //1.string->uint32_t 2.uint32_t 必須是網(wǎng)絡(luò)序列的//local.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(_sockfd,(const struct sockaddr *)&local,sizeof(local))<0){log.LogMessage(FATAL,"bind error , error: %d, error string : %s",errno,strerror(errno));exit(BIND_ERR);}log.LogMessage(INFO,"bind success , error: %d, error string : %s",errno,strerror(errno));}void Run(func_t func){_isrunning = true;char inbuffer[size];while(_isrunning){struct sockaddr_in client;socklen_t len = sizeof(client);std::cout<<"server is run!!!"<<std::endl;ssize_t n = recvfrom(_sockfd,inbuffer,sizeof(inbuffer) - 1,0,(struct sockaddr *)&client,&len);if(n<0){log.LogMessage(WARNING,"recvfrom error, errno: %d ,errno string : %s",errno,strerror(errno));continue;}uint16_t clientport = ntohs(client.sin_port);std::string clientip = inet_ntoa(client.sin_addr);inbuffer[n] = 0;//充當(dāng)了一次數(shù)據(jù)的處理std::string info = inbuffer;std::string echo_string = func(info,clientport,clientip);sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,(struct sockaddr*)&client,len);}}~UdpServer() {if(_sockfd>0) close(_sockfd);}private:int _sockfd;//網(wǎng)絡(luò)文件描述符std::string _ip;//字符串類型ip地址uint16_t _port;//服務(wù)器進(jìn)程的端口號   bool _isrunning;
};

Main.cc

#include"UdpServer.hpp"
#include<memory>
#include<iostream>
#include<cstdio>
#include<vector>void Usage(std::string proc)
{std::cout<<"\n\rUsage: "<<proc<<" port[1024+]\n"<<std::endl;
}std::string Handler(const std::string& str,uint16_t & clientport,const std::string& clientip)
{std::cout<<"[ ip: "<< clientip<<" port: "<<clientport<<" ]# ";std::string res = "server get a message: ";res+=str;std::cout<<res<<std::endl;return res;
}bool SafeCheck(const std::string & cmd)
{std::vector<std::string> key_word = {"rm","mv","cp","kill","sudo","unlink","uninstall","yum","top"};for(auto &word:key_word){auto pos = cmd.find(word);if(pos!=std::string::npos) return false;}return true;
}std::string ExcuteCommand(const std::string & cmd)
{if(!SafeCheck(cmd)) return "bad man";FILE* fp = popen(cmd.c_str(),"r");if(nullptr == fp){perror("popen error");return "error";}std::string result;char buffer[4096];while(true){char * getc = fgets(buffer,sizeof(buffer),fp);if(nullptr == getc){break;}result+=buffer;}pclose(fp);return result;}int main(int argc,char* argv[])
{if(argc!=2){Usage(argv[0]);exit(1);}uint16_t port = std::stoi(argv[1]);std::unique_ptr<UdpServer> svr(new UdpServer(port));svr->Init();svr->Run(Handler);    return 0;
}

UdpClient.cc(客戶端代碼)

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}// ./udpclient serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(0);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport); //?server.sin_addr.s_addr = inet_addr(serverip.c_str());socklen_t len = sizeof(server);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socker error" << endl;return 1;}// client 要bind嗎?要!只不過不需要用戶顯示的bind!一般有OS自由隨機(jī)選擇!// 一個端口號只能被一個進(jìn)程bind,對server是如此,對于client,也是如此!// 其實(shí)client的port是多少,其實(shí)不重要,只要能保證主機(jī)上的唯一性就可以!// 系統(tǒng)什么時(shí)候給我bind呢?首次發(fā)送數(shù)據(jù)的時(shí)候string message;char buffer[1024];while (true){cout << "Please Enter@ ";getline(cin, message);cout<<message<<endl;// std::cout << message << std::endl;// 1. 數(shù)據(jù) 2. 給誰發(fā)sendto(sockfd, message.c_str(), message.size(), 0, (const sockaddr *)&server, len);struct sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t s = recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr*)&temp, &len);if(s > 0)           {buffer[s] = 0;cout << buffer << endl;}}close(sockfd);return 0;
}

日志類:

#pragma once#include <iostream>
#include <cstdarg>
#include <ctime>
#include <string>
#include <unistd.h>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>enum
{DEBUG = 0,INFO,WARNING,ERROR,FATAL
};enum
{Screen = 10,Onefile,Classfile
};std::string LevelToString(int level)
{switch (level){case DEBUG:return "Debug";case INFO:return "Info";case WARNING:return "Warning";case ERROR:return "Error";case FATAL:return "Fatal";default:return "Unknown";}
}const int defaultstyle = Screen;
const std::string default_filename = "log.";
const std::string logdir="log";class Log
{
public:Log():style(defaultstyle),filename(default_filename){mkdir(logdir.c_str(),0775);}void Enable(int sty){style = sty;}std::string TimestampToLocalTime(){time_t curr = time(nullptr);struct tm *currtime = localtime(&curr);char time_buffer[128];snprintf(time_buffer, sizeof(time_buffer), "%d-%d-%d %d:%d:%d",currtime->tm_year + 1900, currtime->tm_mon, currtime->tm_mday, currtime->tm_hour,currtime->tm_min, currtime->tm_sec);return time_buffer;}void WriteLog(const std::string &levelstr, const std::string &message){switch (style){case Screen:std::cout << message<<std::endl;break;case Onefile:WriteLogToOnefile("all", message);break;case Classfile:WriteLogToClassfile(levelstr, message);break;default:break;}}void WriteLogToOnefile(const std::string &logname, const std::string &message){umask(0);int fd = open(logname.c_str(),O_CREAT | O_WRONLY | O_APPEND,0666);if(fd<0)return;write(fd,message.c_str(),message.size());close(fd);// std::ofstream out(logname);// if (!out.is_open())//     return;// out.write(message.c_str(), message.size());// out.close();}void WriteLogToClassfile(const std::string &levelstr, const std::string &message){std::string logname = logdir;logname+="/";logname+=filename;logname += levelstr;WriteLogToOnefile(logname, message);}void LogMessage(int level, const char *format, ...) // 類c的日志接口{char rightbuffer[1024];va_list args;va_start(args, format);vsnprintf(rightbuffer, sizeof(rightbuffer), format, args);va_end(args);char leftbuffer[1024];std::string curtime = TimestampToLocalTime();std::string levelstr = LevelToString(level);std::string idstr = std::to_string(getpid());snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%s][%s]",levelstr.c_str(), curtime.c_str(), idstr.c_str());std::string logInfo = leftbuffer;logInfo += rightbuffer;WriteLog(levelstr, logInfo);}~Log() {}private:int style;std::string filename;
};Log log;class Conf
{
public:Conf(){log.Enable(Screen);}~Conf(){}
};Conf conf;

Makefile

.PHONY:all
all:udpserver udpclientudpserver:Main.ccg++ -o $@ $^ -g -std=c++11
udpclient:UdpClient.ccg++ -o $@ $^ -g -std=c++11.PHONY:clean
clean:rm -rf udpserver udpclient

運(yùn)行結(jié)果:

實(shí)現(xiàn)了客戶端,服務(wù)端雙方交互,當(dāng)然我們這只是簡單的進(jìn)行數(shù)據(jù)處理,其實(shí)還可以通過實(shí)現(xiàn)其他功能,這里可以發(fā)揮自己的想象去寫。

地址轉(zhuǎn)換函數(shù)

這里只介紹基于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_addr的函數(shù):

in_addr轉(zhuǎn)字符串的函數(shù):

其中inet_pton和inet_ntop不僅可以轉(zhuǎn)換IPv4的in_addr,還可以轉(zhuǎn)換IPv6的in6_addr,因此函數(shù)接口是void*addrptr。

關(guān)于inet_ntoa

inet_ntoa這個函數(shù)返回了一個char*, 很顯然是這個函數(shù)自己在內(nèi)部為我們申請了一塊內(nèi)存來保存ip的結(jié)果. 那么是否需要調(diào)用者手動釋放呢?

man手冊上說, inet_ntoa函數(shù), 是把這個返回結(jié)果放到了靜態(tài)存儲區(qū). 這個時(shí)候不需要我們手動進(jìn)行釋放.

那么問題來了, 如果我們調(diào)用多次這個函數(shù), 會有什么樣的效果呢? 參見如下代碼:

#include<stdio.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{struct sockaddr_in addr1;struct sockaddr_in addr2;addr1.sin_addr.s_addr=0;addr2.sin_addr.s_addr=0xffffffff;char* ptr1 = inet_ntoa(addr1.sin_addr);char* ptr2 = inet_ntoa(addr2.sin_addr);printf("ptr1: %s,ptr2: %s\n",ptr1,ptr2);return 0;
}

運(yùn)行結(jié)果:

因?yàn)閕net_ntoa把結(jié)果放到自己內(nèi)部的一個靜態(tài)存儲區(qū), 這樣第二次調(diào)用時(shí)的結(jié)果會覆蓋掉上一次的結(jié)果

  • 如果有多個線程調(diào)用 inet_ntoa, 是否會出現(xiàn)異常情況呢?
  • 在APUE中, 明確提出inet_ntoa不是線程安全的函數(shù);
  • 但是在centos7上測試, 并沒有出現(xiàn)問題, 可能內(nèi)部的實(shí)現(xiàn)加了互斥鎖;
  • 在多線程環(huán)境下, 推薦使用inet_ntop, 這個函數(shù)由調(diào)用者提供一個緩沖區(qū)保存結(jié)果, 可以規(guī)避線程安全問題;

如果測試如下代碼:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
void *Func1(void *p)
{struct sockaddr_in *addr = (struct sockaddr_in *)p;while (1){char *ptr = inet_ntoa(addr->sin_addr);printf("addr1: %s\n", ptr);}return NULL;
}
void *Func2(void *p)
{struct sockaddr_in *addr = (struct sockaddr_in *)p;while (1){char *ptr = inet_ntoa(addr->sin_addr);printf("addr2: %s\n", ptr);}return NULL;
}
int main()
{pthread_t tid1 = 0;struct sockaddr_in addr1;struct sockaddr_in addr2;addr1.sin_addr.s_addr = 0;addr2.sin_addr.s_addr = 0xffffffff;pthread_create(&tid1, NULL, Func1, &addr1);pthread_t tid2 = 0;pthread_create(&tid2, NULL, Func2, &addr2);pthread_join(tid1, NULL);pthread_join(tid2, NULL);return 0;
}

運(yùn)行結(jié)果:

這段代碼試圖創(chuàng)建兩個線程,Func1?和?Func2,它們分別無限循環(huán)地打印兩個?sockaddr_in?結(jié)構(gòu)的 IP 地址。這兩個?sockaddr_in?結(jié)構(gòu),addr1?和?addr2,被初始化為具有特定的?sin_addr.s_addr?值。

addr1.sin_addr.s_addr?被初始化為?0,這在 IPv4 地址中通常表示一個未指定的地址,或者說是無效的地址。

addr2.sin_addr.s_addr?被初始化為?0xffffffff,這在 IPv4 地址中通常表示廣播地址。

然而,代碼中有一些需要注意的地方:

  1. inet_ntoa的靜態(tài)緩沖區(qū)inet_ntoa?函數(shù)使用靜態(tài)緩沖區(qū)來存儲轉(zhuǎn)換后的字符串。這意味著如果兩個線程同時(shí)調(diào)用?inet_ntoa,它們可能會覆蓋彼此的緩沖區(qū),導(dǎo)致不可預(yù)測的結(jié)果。因此,在多線程環(huán)境中使用?inet_ntoa?是不安全的。
  2. 無限循環(huán):兩個線程都包含一個無限循環(huán),這會導(dǎo)致程序永遠(yuǎn)不會退出,除非被外部因素(如用戶終止)中斷。
  3. pthread_join:雖然代碼中包含了?pthread_join?調(diào)用,但由于線程中的無限循環(huán),這些調(diào)用實(shí)際上永遠(yuǎn)不會返回,因此?main?函數(shù)也永遠(yuǎn)不會結(jié)束。

測試這段代碼時(shí),你會看到兩個線程分別不停地打印出相同的 IP 地址字符串,但由于?inet_ntoa?的問題,這些字符串可能會被互相覆蓋,導(dǎo)致輸出變得混亂。

此外,具體的輸出取決于操作系統(tǒng)的具體實(shí)現(xiàn)和線程調(diào)度的行為。在某些情況下,你可能會看到?addr1?和?addr2?交替出現(xiàn),而在其他情況下,你可能會看到某個地址連續(xù)出現(xiàn)多次,然后被另一個地址覆蓋。

總的來說,這段代碼并不是一個好的示例,因?yàn)樗诙嗑€程環(huán)境中不正確地使用了?inet_ntoa,并且包含了無限循環(huán),這會導(dǎo)致程序行為不可預(yù)測且難以管理。

如果你需要在多線程環(huán)境中處理 IP 地址,建議使用更安全的函數(shù),如?inet_ntop,并確保正確管理線程的生命周期和同步。

http://aloenet.com.cn/news/46709.html

相關(guān)文章:

  • 做平臺和獨(dú)立建網(wǎng)站綜合型b2b電子商務(wù)平臺網(wǎng)站
  • 免費(fèi)的素材網(wǎng)站網(wǎng)站如何做關(guān)鍵詞優(yōu)化
  • 個人網(wǎng)站發(fā)布怎么做優(yōu)化大師官網(wǎng)入口
  • 網(wǎng)站建設(shè)總體方案設(shè)計(jì)下載優(yōu)化大師app
  • web前端工程師職業(yè)規(guī)劃seo推廣優(yōu)化的方法
  • 公司網(wǎng)站建設(shè)有什么好處2345網(wǎng)址導(dǎo)航下載
  • 網(wǎng)站建設(shè)的公司在哪找企業(yè)推廣策略
  • 做網(wǎng)站犯法嗎小廣告圖片
  • 類似網(wǎng)站的建設(shè)西安seo網(wǎng)絡(luò)優(yōu)化公司
  • 網(wǎng)站建設(shè)個人網(wǎng)站佛山網(wǎng)絡(luò)推廣哪里好
  • 網(wǎng)站備案信息傳網(wǎng)店推廣聯(lián)盟
  • wordpress 小工具 調(diào)用seo是什么崗位
  • 山東日照建設(shè)網(wǎng)站微信小程序怎么開通
  • 做藥材生意的網(wǎng)站免費(fèi)下載百度app最新版本
  • 濟(jì)南網(wǎng)絡(luò)廣播電視臺北京關(guān)鍵詞優(yōu)化報(bào)價(jià)
  • 域名服務(wù)器的四種類型營口seo
  • 網(wǎng)站建設(shè)需要哪些方面愛站網(wǎng)權(quán)重查詢
  • 深圳燃?xì)夤镜刂吩谀睦锕枮Iseo關(guān)鍵字優(yōu)化
  • 網(wǎng)站首頁大圖怎么做優(yōu)化推廣網(wǎng)站排名
  • 知名網(wǎng)站建設(shè)定制如何聯(lián)系百度客服
  • 電梯配件做外貿(mào)在哪個網(wǎng)站上海網(wǎng)絡(luò)推廣招聘
  • 網(wǎng)站開發(fā)調(diào)研方案中小企業(yè)網(wǎng)絡(luò)營銷現(xiàn)狀
  • 如何做網(wǎng)站首頁百度查重
  • 網(wǎng)站代碼制作軟件網(wǎng)絡(luò)營銷五種方法
  • wordpress國外主題慢點(diǎn)擊排名優(yōu)化
  • 網(wǎng)站后臺動態(tài)播放怎么做的招代理最好的推廣方式
  • 網(wǎng)站如何兼容大多瀏覽器怎么注冊電商平臺
  • 溧陽網(wǎng)站設(shè)計(jì)唐山seo排名
  • 做安全題目是哪個網(wǎng)站長沙百度網(wǎng)站快速排名
  • 蘇州網(wǎng)站建設(shè)設(shè)計(jì)公司免費(fèi)網(wǎng)站建設(shè)制作