linux java提高recv q,linux – 使用Recv-Q和Send-Q

netstat输出中Recv-Q和Send-Q列的用途是什么?我如何在现实场景中使用它?

在我的系统上,两个列始终显示为零.这是什么意思?

解决方法:

从我的手册页:

Recv-Q

Established: The count of bytes not copied by the user program

connected to this socket.

Listening: Since Kernel 2.6.18 this column contains the current syn

backlog.

Send-Q

Established: The count of bytes not acknowledged by the remote

host.

Listening: Since Kernel 2.6.18 this column contains the maximum size

of the syn backlog.

如果你把它粘到0,这只意味着连接两端的应用程序和它们之间的网络都正常.实际的即时值可能与0不同,但是这种短暂的,逃逸的方式使您无法实际观察它.

现实生活场景的示例,其中可能与0不同(在已建立的连接上,但我认为您会明白这一点):

我最近在Linux嵌入式设备上与一个(设计不佳的)第三方设备进行通信.在这个第三方设备上,应用程序有时显然卡住,而不是读取它在TCP连接上收到的数据,导致其TCP窗口下降到0并在那里停留数十秒(在镜像端口之间通过wireshark观察到的现象) 2个主人).在这种情况下:

> Recv-Q:在第三方设备上运行netstat(我没有

意味着可能已经显示出增加的Recv-Q,达到一些屋顶值

另一边(我)停止发送数据因为窗口得到了

降至0,因为应用程序没有读取可用的数据

它的套接字,这些数据在TCP实现中保持缓冲

操作系统,而不是卡住的应用程序 – >来自接收者

方面,申请问题.

> Send-Q:在我身边运行netstat(我没试过,因为

1 / wireshark的问题很清楚,这是上面的第一个案例

并且2 /这不是100%可再现的)可能已经显示非零

Send-Q,如果操作系统级别的另一端TCP实现有

被卡住并停止确认我的数据 – >来自发件人

接收TCP实现(通常在操作系统级别)问题.

请注意,如果我的Linux TCP实现行为不端并且在TCP窗口下降到0后继续发送数据,上面描述的Send-Q场景也可能是发送方问题(我方):接收方没有更多的空间这个数据 – >不承认.

另请注意,Send-Q问题可能不是由于接收器引起的,而是由发送方和接收方之间的某些路由问题引起的.一些数据包在两台主机之间“在运行中”,但尚未确认.另一方面,Recv-Q问题绝对是在主机上:收到的数据包,已确认,但尚未从应用程序中读取.

编辑:

在现实生活中,对于你可以合理预期的非蹩脚的主机和应用程序,我敢打赌Send-Q问题大部分时间是由于发送方和接收方之间的某些路由问题/网络性能不佳引起的.永远不要忘记“正在运行”的数据包状态:

>数据包可能位于发送方和接收方之间的网络上,

>(或收到但ACK还没发送,见上文)

>或者ACK可能在接收者和发送者之间的网络上.

它需要RTT(往返时间)才能发送数据包然后进行确认.

标签:netstat,linux,networking,unix

来源: https://codeday.me/bug/20190930/1835134.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用 epoll 实现的简单的 TCP 服务器和客户端的例子。服务器和客户端都是非阻塞的,使用 epoll 监听和处理文件描述符事件。其中,服务器使用了多线程技术,每个线程负责处理一个客户端连接。 服务器代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <signal.h> #include <netinet/in.h> #include <sys/epoll.h> #include <pthread.h> #define MAX_EVENTS 1024 #define BUF_SIZE 1024 #define THREAD_NUM 4 int listen_fd; int epoll_fd; pthread_t thread_pool[THREAD_NUM]; void setnonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); } void add_event(int fd, int events) { struct epoll_event ev; ev.events = events; ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev); } void del_event(int fd, int events) { struct epoll_event ev; ev.events = events; ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev); } void mod_event(int fd, int events) { struct epoll_event ev; ev.events = events; ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ev); } void *worker(void *arg) { int client_fd = *(int*)arg; char buf[BUF_SIZE]; int nread; while (1) { nread = recv(client_fd, buf, BUF_SIZE, 0); if (nread == -1) { if (errno == EAGAIN) { printf("recv EAGAIN\n"); break; } else { perror("recv"); break; } } else if (nread == 0) { printf("client close\n"); break; } else { printf("recv: %s\n", buf); if (send(client_fd, buf, nread, 0) == -1) { perror("send"); break; } } } close(client_fd); pthread_exit(NULL); } void *accepter(void *arg) { struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_fd; int i; while (1) { client_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len); if (client_fd == -1) { if (errno == EAGAIN) { printf("accept EAGAIN\n"); continue; } else { perror("accept"); break; } } else { setnonblocking(client_fd); add_event(client_fd, EPOLLIN|EPOLLET); printf("new client: %d\n", client_fd); } } close(listen_fd); pthread_exit(NULL); } int main(int argc, char *argv[]) { struct sockaddr_in server_addr; int port = 8888; struct epoll_event events[MAX_EVENTS]; int nready; int i, j; if (argc > 1) { port = atoi(argv[1]); } listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd == -1) { perror("socket"); exit(1); } setnonblocking(listen_fd); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); if (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { perror("bind"); exit(1); } if (listen(listen_fd, 1024) == -1) { perror("listen"); exit(1); } epoll_fd = epoll_create(MAX_EVENTS); if (epoll_fd == -1) { perror("epoll_create"); exit(1); } add_event(listen_fd, EPOLLIN|EPOLLET); for (i = 0; i < THREAD_NUM; i++) { if (pthread_create(&thread_pool[i], NULL, accepter, NULL) == -1) { perror("pthread_create"); exit(1); } } while (1) { nready = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nready == -1) { if (errno == EINTR) { continue; } else { perror("epoll_wait"); break; } } for (i = 0; i < nready; i++) { if (events[i].data.fd == listen_fd) { continue; } if (events[i].events & EPOLLIN) { pthread_t thread_id; int client_fd = events[i].data.fd; del_event(client_fd, EPOLLIN|EPOLLET); if (pthread_create(&thread_id, NULL, worker, (void*)&client_fd) == -1) { perror("pthread_create"); } } } } for (i = 0; i < THREAD_NUM; i++) { if (pthread_join(thread_pool[i], NULL) == -1) { perror("pthread_join"); } } close(epoll_fd); return 0; } ``` 客户端代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/epoll.h> #define MAX_EVENTS 1024 #define BUF_SIZE 1024 void setnonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); } void add_event(int fd, int events) { struct epoll_event ev; ev.events = events; ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev); } void del_event(int fd, int events) { struct epoll_event ev; ev.events = events; ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev); } void mod_event(int fd, int events) { struct epoll_event ev; ev.events = events; ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ev); } int main(int argc, char *argv[]) { struct sockaddr_in server_addr; char *ip = "127.0.0.1"; int port = 8888; int sockfd; struct epoll_event events[MAX_EVENTS]; int nready; char buf[BUF_SIZE]; int nread, nwrite; int i; if (argc > 1) { ip = argv[1]; } if (argc > 2) { port = atoi(argv[2]); } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(1); } setnonblocking(sockfd); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(ip); server_addr.sin_port = htons(port); if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { if (errno != EINPROGRESS) { perror("connect"); exit(1); } } epoll_fd = epoll_create(MAX_EVENTS); if (epoll_fd == -1) { perror("epoll_create"); exit(1); } add_event(sockfd, EPOLLOUT); while (1) { nready = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nready == -1) { if (errno == EINTR) { continue; } else { perror("epoll_wait"); break; } } for (i = 0; i < nready; i++) { if (events[i].events & EPOLLOUT) { del_event(sockfd, EPOLLOUT); printf("connected\n"); break; } } } while (1) { scanf("%s", buf); if (strcmp(buf, "quit") == 0) { break; } nwrite = send(sockfd, buf, strlen(buf), 0); if (nwrite == -1) { perror("send"); break; } nread = recv(sockfd, buf, BUF_SIZE, 0); if (nread == -1) { if (errno == EAGAIN) { printf("recv EAGAIN\n"); continue; } else { perror("recv"); break; } } else if (nread == 0) { printf("server close\n"); break; } else { printf("recv: %s\n", buf); } } close(sockfd); close(epoll_fd); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值