欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中套接字庫(kù)sockpp的使用詳解

 更新時(shí)間:2023年11月15日 11:29:38   作者:fengbingchun  
sockpp是一個(gè)開(kāi)源、簡(jiǎn)單、現(xiàn)代的C++套接字庫(kù),這篇文章主要為大家詳細(xì)介紹一下套接字庫(kù)sockpp的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下

sockpp是一個(gè)開(kāi)源、簡(jiǎn)單、現(xiàn)代的C++套接字庫(kù),地址為:https://github.com/fpagliughi/sockpp,最新發(fā)布版本為0.8.1,license為BSD-3-Clause。目前支持Linux、Windows、Mac上的IPv4、IPv6和Unix域套接字。其它*nix和POSIX系統(tǒng)只需很少的修改或無(wú)需修改即可工作。

1.套接字基類(lèi)包裝(wrap)系統(tǒng)套接字句柄,并維持其生命周期。當(dāng)C++對(duì)象超出范圍時(shí),它會(huì)關(guān)閉底層套接字句柄。套接字對(duì)象通常是可移動(dòng)的,但不可復(fù)制??梢允褂?std::move()將套接字從一個(gè)作用域(或線程)傳輸?shù)搅硪粋€(gè)作用域。

2.庫(kù)中的所有代碼都位于sockpp C++命名空間內(nèi)。

3.TCP和其它"流"網(wǎng)絡(luò)應(yīng)用程序通常設(shè)置為服務(wù)器或客戶端。接受器用于創(chuàng)建TCP/流服務(wù)器。它綁定一個(gè)地址并偵聽(tīng)已知端口以接受傳入連接。 當(dāng)連接被接受時(shí),會(huì)創(chuàng)建一個(gè)新的流式套接字。該新套接字可以直接處理或移動(dòng)到線程(或線程池)進(jìn)行處理。

相反,要?jiǎng)?chuàng)建TCP客戶端,需要?jiǎng)?chuàng)建連接器對(duì)象并將其連接到已知地址(通常是主機(jī)和套接字)的服務(wù)器。連接后,套接字是一種流式套接字,可以直接用于讀寫(xiě)。

對(duì)于IPv4,sockpp::tcp_acceptor和sockpp::tcp_connector類(lèi)分別用于創(chuàng)建服務(wù)器和客戶端。它們使用sockpp::inet_address類(lèi)來(lái)指定由32位主機(jī)地址和16位端口號(hào)組成的端點(diǎn)地址。

sockpp::tcp_acceptor通常位于一個(gè)循環(huán)中接受新連接,并將它們傳遞給另一個(gè)進(jìn)程、線程或線程池以與客戶端交互。

TCP客戶端稍微簡(jiǎn)單一些,創(chuàng)建一個(gè)sockpp::tcp_connector對(duì)象并連接,然后可以直接讀寫(xiě)數(shù)據(jù)。

4.每個(gè)套接字類(lèi)的默認(rèn)構(gòu)造函數(shù)不執(zhí)行任何操作,只是將底層句柄設(shè)置為INVALID_SOCKET。它們不創(chuàng)建套接字對(duì)象。

5.套接字對(duì)象不是線程安全的。想要有多個(gè)線程從套接字讀取或?qū)懭胩捉幼值膽?yīng)用程序應(yīng)該使用某種形式的序列化,例如std::mutex來(lái)保護(hù)訪問(wèn)。套接字可以安全地從一個(gè)線程移動(dòng)到(moved)另一個(gè)線程。這是服務(wù)器的一種常見(jiàn)模式,它使用一個(gè)線程接受傳入連接,然后將新套接字傳遞給另一個(gè)線程或線程池進(jìn)行處理。

由于套接字無(wú)法復(fù)制,唯一的選擇是將套接字移動(dòng)到這樣的函數(shù)。這是一種常見(jiàn)的模式,尤其是在客戶端應(yīng)用程序中,讓一個(gè)線程從套接字讀取數(shù)據(jù),另一個(gè)線程向套接字寫(xiě)入數(shù)據(jù)。在這種情況下,底層套接字句柄可以被認(rèn)為是線程安全的(一個(gè)讀線程和一個(gè)寫(xiě)線程)。但即使在這種情況下,sockpp::socket對(duì)象仍然不是線程安全的,特別是由于緩存的錯(cuò)誤值(cached error value)。寫(xiě)入線程可能會(huì)看到讀取線程上發(fā)生的錯(cuò)誤,反之亦然。

這種情況的解決方案是使用socket::clone()方法來(lái)復(fù)制套接字。這將使用系統(tǒng)的dup()函數(shù)或類(lèi)似的函數(shù)創(chuàng)建另一個(gè)帶有套接字句柄的重復(fù)副本的套接字。這樣做的另一個(gè)好處是套接字的每個(gè)副本都可以保持獨(dú)立的生命周期。在兩個(gè)對(duì)象超出范圍之前,底層套接字不會(huì)關(guān)閉。

在Windows和Linux上編譯的sockpp的shell腳本如下:

#! /bin/bash
 
if [ $# != 2 ]; then
    echo "Error: requires two parameters: 1: windows or linux; 2: release or debug"
    echo "For example: $0 windows debug"
    exit -1
fi
 
if [ $1 != "windows"  ] && [ $1 != "linux" ]; then
    echo "Error: the first parameter can only be windows or linux"
    exit -1
fi
 
if [ $2 != "debug" ] && [ $2 != "release" ]; then
    echo "Error: the second parameter can only be debug or release"
    exit -1
fi
 
if [ $1 == "windows" ] && [ $2 == "debug" ]; then
    cmake \
        -G"Visual Studio 17 2022" -A x64 \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DSOCKPP_BUILD_SHARED=OFF \
        -DSOCKPP_BUILD_STATIC=ON \
        -DSOCKPP_BUILD_EXAMPLES=ON \
        -DCMAKE_INSTALL_PREFIX=install/debug \
        -Bbuild \
        .
    
    cmake --build build/ --target install --config debug
fi
 
if [ $1 == "windows" ] && [ $2 == "release" ]; then
    cmake \
        -G"Visual Studio 17 2022" -A x64 \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DSOCKPP_BUILD_SHARED=OFF \
        -DSOCKPP_BUILD_STATIC=ON \
        -DSOCKPP_BUILD_EXAMPLES=ON \
        -DCMAKE_INSTALL_PREFIX=install/release \
        -Bbuild \
        .
 
    cmake --build build/ --target install --config release
fi
 
if [ $1 == "linux" ] && [ $2 == "debug" ]; then
    cmake \
        -DCMAKE_BUILD_TYPE=Debug \
        -DSOCKPP_BUILD_SHARED=OFF \
        -DSOCKPP_BUILD_STATIC=ON \
        -DSOCKPP_BUILD_EXAMPLES=ON \
        -DCMAKE_INSTALL_PREFIX=install/debug \
        -Bbuild \
        .
    
    cmake --build build/ --target install --config debug
fi
 
if [ $1 == "linux" ] && [ $2 == "release" ]; then
    cmake \
        -DCMAKE_BUILD_TYPE=Release \
        -DSOCKPP_BUILD_SHARED=OFF \
        -DSOCKPP_BUILD_STATIC=ON \
        -DSOCKPP_BUILD_EXAMPLES=ON \
        -DCMAKE_INSTALL_PREFIX=install/release \
        -Bbuild \
        .
 
    cmake --build build/ --target install --config release
fi
 
rc=$?
if [[ ${rc} != 0 ]]; then
    echo "Error: please check: ${rc}"
	exit ${rc}
fi

以下為IPv4的測(cè)試代碼:

1.客戶端測(cè)試代碼如下:

int test_sockpp_client()
{
    sockpp::initialize();
 
    sockpp::tcp_connector conn({host, port});
	if (!conn) {
		std::cerr << "Error: connecting to server at: "
			<< sockpp::inet_address(host, port)
			<< ", message: " << conn.last_error_str() << std::endl;
		return -1;
	}
 
    std::cout << "created a connection from: " << conn.address() << std::endl;
	std::cout << "created a connection to " << conn.peer_address() << std::endl;
 
    // set a timeout for the responses
    if (!conn.read_timeout(std::chrono::seconds(5))) {
        std::cerr << "Error: setting timeout on TCP stream: " << conn.last_error_str() << std::endl;
    }
 
    const std::vector<std::string> addr{"csdn", "github", "gitlab"};
    std::unique_ptr<unsigned char[]> buf(new unsigned char[len]);
    int index{0};
 
	std::atomic<bool> quit{ false };
	std::thread th([&quit] {
		std::this_thread::sleep_for(std::chrono::seconds(20));
		quit = true;
	});
 
	while (true) {
		if (quit) break;
 
        auto ret = conn.write(addr[index]);
        if (ret != addr[index].size()) {
            std::cerr << "Error: writing to the TCP stream: " << conn.last_error_str() << std::endl;
            break;
        }
 
		memset(buf.get(), 0, len);
        ret = conn.read(buf.get(), len);
        if (ret == -1) {
            std::cerr << "Error: reading from TCP stream: " << conn.last_error_str() << std::endl;
            break;
        }
 
        std::cout << addr[index] << ": " << buf.get() << std::endl;
 
        if (++index == addr.size()) index = 0;
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
 
	th.join();
    return 0;
}

2.服務(wù)器端測(cè)試代碼如下:

int test_sockpp_server()
{
    sockpp::initialize();
 
    sockpp::tcp_acceptor acc(port);
	if (!acc) {
		std::cerr << "Error: creating the acceptor: " << acc.last_error_str() << std::endl;
		return -1;
	}
 
	while (true) {
		sockpp::inet_address peer;
		// accept a new client connection
		sockpp::tcp_socket sock = acc.accept(&peer);
		std::cout << "received a connection request from: " << peer << std::endl;
		if (!sock) {
			std::cerr << "Error: accepting incoming connection: " << acc.last_error_str() << std::endl;
		}
		else {
			// create a thread and transfer the new stream to it
			std::thread th2(run_echo, std::move(sock));
			th2.detach();
		}
	}
 
    return 0;
}

3.輔助code如下所示:

namespace {
 
constexpr char* host{"127.0.0.1"};
constexpr in_port_t port{ 8888 };
constexpr int len {64};
 
void run_echo(sockpp::tcp_socket sock)
{
	std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
 
	std::map<std::string, std::string> addr;
	addr["csdn"] = "https://blog.csdn.net/fengbingchun";
	addr["github"] = "https://github.com/fengbingchun";
 
	std::unique_ptr<unsigned char[]> buf(new unsigned char[len]);
 
	while (true) {
		memset(buf.get(), 0, len);
		auto ret = sock.read(buf.get(), len);
		if (ret == -1) {
			std::cerr << "Error: reading from TCP stream: " << sock.last_error_str() << std::endl;
            break;
		}
 
		auto it = addr.find(std::string((char*)buf.get()));
		if (it != addr.end()) {
			sock.write(it->second);
		}
		else
			sock.write("unkonwn");
	}
}
 
} // namespace

Windows上執(zhí)行結(jié)果如下所示:模擬1個(gè)服務(wù)器端,3個(gè)客戶端

Linux上執(zhí)行結(jié)果如下圖所示:模擬1個(gè)服務(wù)器端,3個(gè)客戶端

GitHubhttps://github.com/fengbingchun/OpenSSL_Test

到此這篇關(guān)于C++中套接字庫(kù)sockpp的使用詳解的文章就介紹到這了,更多相關(guān)C++套接字庫(kù)sockpp內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言循環(huán)鏈表實(shí)現(xiàn)貪吃蛇游戲

    C語(yǔ)言循環(huán)鏈表實(shí)現(xiàn)貪吃蛇游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言循環(huán)鏈表實(shí)現(xiàn)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • 用C語(yǔ)言遞歸實(shí)現(xiàn)火車(chē)調(diào)度算法詳解

    用C語(yǔ)言遞歸實(shí)現(xiàn)火車(chē)調(diào)度算法詳解

    本文主要介紹了用C語(yǔ)言遞歸實(shí)現(xiàn)火車(chē)調(diào)度算法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C語(yǔ)言中的指針 初階

    C語(yǔ)言中的指針 初階

    這篇文章主要介紹的是關(guān)于初級(jí)階段學(xué)習(xí)C語(yǔ)言中指針的一些內(nèi)容,那就是指針是什么?簡(jiǎn)單的說(shuō),就是通過(guò)它能找到以它為地址的內(nèi)存單元。下面文章我們就來(lái)詳細(xì)介紹該內(nèi)容,需要的朋友可以參考一下
    2021-10-10
  • 一張圖總結(jié)C++中關(guān)于指針的那些事

    一張圖總結(jié)C++中關(guān)于指針的那些事

    今天小編就為大家分享一篇關(guān)于一圖總結(jié)C++中關(guān)于指針的那些事,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-02-02
  • 利用C語(yǔ)言實(shí)現(xiàn)順序表的實(shí)例操作

    利用C語(yǔ)言實(shí)現(xiàn)順序表的實(shí)例操作

    順序表是線性表中的一種重要的數(shù)據(jù)結(jié)構(gòu),也是最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),所以他不僅是學(xué)習(xí)中的重點(diǎn),也是應(yīng)用開(kāi)發(fā)非常常用的一種數(shù)據(jù)結(jié)構(gòu)。這篇文章介紹如何利用C語(yǔ)言實(shí)現(xiàn)順序表。
    2016-08-08
  • C語(yǔ)言讀寫(xiě)配置文件的方法

    C語(yǔ)言讀寫(xiě)配置文件的方法

    這篇文章主要介紹了C語(yǔ)言讀寫(xiě)配置文件的方法,包括C語(yǔ)言讀寫(xiě)ini配置文件所涉及的文件讀寫(xiě)技巧,以及完整的源文件及頭文件實(shí)現(xiàn)方法,需要的朋友可以參考下
    2015-07-07
  • C++設(shè)置超時(shí)時(shí)間的簡(jiǎn)單實(shí)現(xiàn)方法

    C++設(shè)置超時(shí)時(shí)間的簡(jiǎn)單實(shí)現(xiàn)方法

    這篇文章主要介紹了C++設(shè)置超時(shí)時(shí)間的簡(jiǎn)單實(shí)現(xiàn)方法,涉及系統(tǒng)函數(shù)setsockopt對(duì)套接口的操作,具有一定的實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • C++高級(jí)數(shù)據(jù)結(jié)構(gòu)之線段樹(shù)

    C++高級(jí)數(shù)據(jù)結(jié)構(gòu)之線段樹(shù)

    這篇文章主要介紹了C++高級(jí)數(shù)據(jù)結(jié)構(gòu)之線段樹(shù),文章圍繞主題的相關(guān)資料展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • Qt音視頻開(kāi)發(fā)之利用ffmpeg實(shí)現(xiàn)倍速播放

    Qt音視頻開(kāi)發(fā)之利用ffmpeg實(shí)現(xiàn)倍速播放

    這篇文章主要為大家詳細(xì)介紹了在Qt音視頻開(kāi)發(fā)中如何利用ffmpeg實(shí)現(xiàn)倍速播放功能(半倍速/2倍速/4倍速/8倍速),感興趣的小伙伴可以了解一下
    2022-11-11
  • C語(yǔ)言每日練習(xí)之進(jìn)制轉(zhuǎn)換

    C語(yǔ)言每日練習(xí)之進(jìn)制轉(zhuǎn)換

    這篇文章主要介紹了C語(yǔ)言進(jìn)制轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-11-11

最新評(píng)論