日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

获取socket对应的接收缓冲区中的可读数据量

發布時間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 获取socket对应的接收缓冲区中的可读数据量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

獲取socket對應的接收緩沖區中的可讀數據量

本文介紹如何獲取當前socket對應的接收緩沖區的可讀數據量

在Linux上可以使用ioctl函數

#include <sys/ioctl.h>int ioctl (int __fd, unsigned long int __request, ...)

來看一個例子:

#include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> #include <poll.h> #include <iostream> #include <string.h> #include <vector> #include <errno.h>//無效fd標記 #define INVALID_FD -1int main(int argc, char* argv[]) {//創建一個偵聽socketint listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd == INVALID_FD){std::cout << "create listen socket error." << std::endl;return -1;}//將偵聽socket設置為非阻塞的int oldSocketFlag = fcntl(listenfd, F_GETFL, 0);int newSocketFlag = oldSocketFlag | O_NONBLOCK;if (fcntl(listenfd, F_SETFL, newSocketFlag) == -1){close(listenfd);std::cout << "set listenfd to nonblock error." << std::endl;return -1;}//復用地址和端口號int on = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on));//初始化服務器地址struct sockaddr_in bindaddr;bindaddr.sin_family = AF_INET;bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);bindaddr.sin_port = htons(3000);if (bind(listenfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) == -1){std::cout << "bind listen socket error." << std::endl;close(listenfd);return -1;}//啟動偵聽if (listen(listenfd, SOMAXCONN) == -1){std::cout << "listen error." << std::endl;close(listenfd);return -1;} std::vector<pollfd> fds;pollfd listen_fd_info;listen_fd_info.fd = listenfd;listen_fd_info.events = POLLIN;listen_fd_info.revents = 0;fds.push_back(listen_fd_info);//是否存在無效的fd標志bool exist_invalid_fd;int n;while (true){exist_invalid_fd = false;n = poll(&fds[0], fds.size(), 1000);if (n < 0){//被信號中斷if (errno == EINTR)continue;//出錯,退出break;}else if (n == 0){//超時,繼續continue;}int size = fds.size();for (size_t i = 0; i < size; ++i){// 事件可讀if (fds[i].revents & POLLIN){if (fds[i].fd == listenfd){//偵聽socket,接受新連接struct sockaddr_in clientaddr;socklen_t clientaddrlen = sizeof(clientaddr);//接受客戶端連接, 并加入到fds集合中int clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientaddrlen);if (clientfd != -1){//將客戶端socket設置為非阻塞的int oldSocketFlag = fcntl(clientfd, F_GETFL, 0);int newSocketFlag = oldSocketFlag | O_NONBLOCK;if (fcntl(clientfd, F_SETFL, newSocketFlag) == -1){close(clientfd);std::cout << "set clientfd to nonblock error." << std::endl; } else{struct pollfd client_fd_info;client_fd_info.fd = clientfd;client_fd_info.events = POLLIN;client_fd_info.revents = 0;fds.push_back(client_fd_info);std::cout << "new client accepted, clientfd: " << clientfd << std::endl;} }}else {//socket 可讀時獲取當前接收緩沖區中的字節數目ulong bytesToRecv = 0;if (ioctl(fds[i].fd, FIONREAD, &bytesToRecv) == 0){std::cout << "bytesToRecv: " << bytesToRecv << std::endl;}//普通clientfd,收取數據char buf[64] = { 0 };int m = recv(fds[i].fd, buf, 64, 0);if (m <= 0){if (errno != EINTR && errno != EWOULDBLOCK){//出錯或對端關閉了連接,關閉對應的clientfd,并設置無效標志位 std::cout << "client disconnected, clientfd: " << fds[i].fd << std::endl;close(fds[i].fd);fds[i].fd = INVALID_FD;exist_invalid_fd = true; } }else{std::cout << "recv from client: " << buf << ", clientfd: " << fds[i].fd << std::endl;}}}else if (fds[i].revents & POLLERR){//TODO: 暫且不處理}}// end outer-for-loopif (exist_invalid_fd){//統一清理無效的fdfor (std::vector<pollfd>::iterator iter = fds.begin(); iter != fds.end(); ){if (iter->fd == INVALID_FD)iter = fds.erase(iter);else++iter;}} }// end while-loop//關閉所有socketfor (std::vector<pollfd>::iterator iter = fds.begin(); iter != fds.end(); ++ iter)close(iter->fd); return 0; }

注意事項:

  • 對于以下代碼,第三個參數bytesToRecv是一個輸出參數,對于大多數其他函數意味著bytesToRecv可以不指定初始化值,因為函數調用成功后會為該變量設置值,但對于ioctl函數是個例外,必須將bytesToRecv初始化為0
  • TCP網絡編程的基本流程

    Linux與C++11多線程編程(學習筆記)

    Linux select函數用法和原理

    socket的阻塞模式和非阻塞模式(send和recv函數在阻塞和非阻塞模式下的表現)

    connect函數在阻塞和非阻塞模式下的行為

    獲取socket對應的接收緩沖區中的可讀數據量

    總結

    以上是生活随笔為你收集整理的获取socket对应的接收缓冲区中的可读数据量的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。