获取socket对应的接收缓冲区中的可读数据量
生活随笔
收集整理的這篇文章主要介紹了
获取socket对应的接收缓冲区中的可读数据量
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
獲取socket對(duì)應(yīng)的接收緩沖區(qū)中的可讀數(shù)據(jù)量
本文介紹如何獲取當(dāng)前socket對(duì)應(yīng)的接收緩沖區(qū)的可讀數(shù)據(jù)量
在Linux上可以使用ioctl函數(shù)
#include <sys/ioctl.h>int ioctl (int __fd, unsigned long int __request, ...)來(lái)看一個(gè)例子:
#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>//無(wú)效fd標(biāo)記 #define INVALID_FD -1int main(int argc, char* argv[]) {//創(chuàng)建一個(gè)偵聽(tīng)socketint listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd == INVALID_FD){std::cout << "create listen socket error." << std::endl;return -1;}//將偵聽(tīng)socket設(shè)置為非阻塞的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;}//復(fù)用地址和端口號(hào)int on = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on));//初始化服務(wù)器地址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;}//啟動(dòng)偵聽(tīng)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);//是否存在無(wú)效的fd標(biāo)志bool exist_invalid_fd;int n;while (true){exist_invalid_fd = false;n = poll(&fds[0], fds.size(), 1000);if (n < 0){//被信號(hào)中斷if (errno == EINTR)continue;//出錯(cuò),退出break;}else if (n == 0){//超時(shí),繼續(xù)continue;}int size = fds.size();for (size_t i = 0; i < size; ++i){// 事件可讀if (fds[i].revents & POLLIN){if (fds[i].fd == listenfd){//偵聽(tīng)socket,接受新連接struct sockaddr_in clientaddr;socklen_t clientaddrlen = sizeof(clientaddr);//接受客戶(hù)端連接, 并加入到fds集合中int clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientaddrlen);if (clientfd != -1){//將客戶(hù)端socket設(shè)置為非阻塞的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 可讀時(shí)獲取當(dāng)前接收緩沖區(qū)中的字節(jié)數(shù)目ulong bytesToRecv = 0;if (ioctl(fds[i].fd, FIONREAD, &bytesToRecv) == 0){std::cout << "bytesToRecv: " << bytesToRecv << std::endl;}//普通clientfd,收取數(shù)據(jù)char buf[64] = { 0 };int m = recv(fds[i].fd, buf, 64, 0);if (m <= 0){if (errno != EINTR && errno != EWOULDBLOCK){//出錯(cuò)或?qū)Χ岁P(guān)閉了連接,關(guān)閉對(duì)應(yīng)的clientfd,并設(shè)置無(wú)效標(biāo)志位 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){//統(tǒng)一清理無(wú)效的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//關(guān)閉所有socketfor (std::vector<pollfd>::iterator iter = fds.begin(); iter != fds.end(); ++ iter)close(iter->fd); return 0; }注意事項(xiàng):
TCP網(wǎng)絡(luò)編程的基本流程
Linux與C++11多線(xiàn)程編程(學(xué)習(xí)筆記)
Linux select函數(shù)用法和原理
socket的阻塞模式和非阻塞模式(send和recv函數(shù)在阻塞和非阻塞模式下的表現(xiàn))
connect函數(shù)在阻塞和非阻塞模式下的行為
獲取socket對(duì)應(yīng)的接收緩沖區(qū)中的可讀數(shù)據(jù)量
總結(jié)
以上是生活随笔為你收集整理的获取socket对应的接收缓冲区中的可读数据量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用java实现新浪爬虫,代码完整剖析(仅
- 下一篇: SQL语句大全,所有的SQL都在这里 !