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

C++中套接字庫sockpp的使用詳解

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

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

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

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

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

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

對于IPv4,sockpp::tcp_acceptor和sockpp::tcp_connector類分別用于創(chuàng)建服務器和客戶端。它們使用sockpp::inet_address類來指定由32位主機地址和16位端口號組成的端點地址。

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

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

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

5.套接字對象不是線程安全的。想要有多個線程從套接字讀取或?qū)懭胩捉幼值膽贸绦驊撌褂媚撤N形式的序列化,例如std::mutex來保護訪問。套接字可以安全地從一個線程移動到(moved)另一個線程。這是服務器的一種常見模式,它使用一個線程接受傳入連接,然后將新套接字傳遞給另一個線程或線程池進行處理。

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

這種情況的解決方案是使用socket::clone()方法來復制套接字。這將使用系統(tǒng)的dup()函數(shù)或類似的函數(shù)創(chuàng)建另一個帶有套接字句柄的重復副本的套接字。這樣做的另一個好處是套接字的每個副本都可以保持獨立的生命周期。在兩個對象超出范圍之前,底層套接字不會關(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的測試代碼:

1.客戶端測試代碼如下:

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.服務器端測試代碼如下:

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個服務器端,3個客戶端

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

GitHubhttps://github.com/fengbingchun/OpenSSL_Test

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

相關(guān)文章

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

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

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

    用C語言遞歸實現(xiàn)火車調(diào)度算法詳解

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

    C語言中的指針 初階

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

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

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

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

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

    C語言讀寫配置文件的方法

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

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

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

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

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

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

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

    C語言每日練習之進制轉(zhuǎn)換

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

最新評論