- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试将 10,000 多个 tcp 客户端连接到我下面的 tcp 服务器。 1-5 秒后,我能够在代码停止并挂起而不终止之前连接 200 到 5000 个客户端。我找不到关于此的任何进一步文档,gprof 探查器无法收集任何数据。
服务器:
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <netdb.h>
#include <errno.h>
#include <iostream>
#ifndef MAXEVENTS
#define MAXEVENTS 64
#endif
#ifndef TX_BUF_SIZE
#define TX_BUF_SIZE (65535)
#endif
#ifndef RX_BUF_SIZE
#define RX_BUF_SIZE (65535)
#endif
char buf[RX_BUF_SIZE];
void user_recv_handler(int efd, int fd, char * buf, int len)
{
int s = -1;
struct epoll_event ev;
ev.data.fd = fd;
ev.events = EPOLLOUT | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev);
//assert(s!=-1);
if(s==-1)
{
fprintf(stderr, "epoll out error.\n");
return;
}
}
struct addrinfo* tcpipv4_getaddrinfo(char* port)
{
struct addrinfo hints;
struct addrinfo *res;
int s;
bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_INET; // ipv4 addrs
hints.ai_socktype = SOCK_STREAM; // TCP
hints.ai_flags = AI_PASSIVE;
s = getaddrinfo(NULL, port, &hints, &res);
//assert(s==0);
if (s)
{
fprintf(stderr, "failed to getaddrinfo: %s\n", gai_strerror(s));
return NULL;
}
return res;
}
struct addrinfo* tcpipv6_getaddrinfo(char* port)
{
struct addrinfo hints;
struct addrinfo *res;
int s;
bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_INET6; // ipv4 addrs
hints.ai_socktype = SOCK_STREAM; // TCP
hints.ai_flags = AI_PASSIVE;
s = getaddrinfo(NULL, port, &hints, &res);
//assert(s==0);
if (s)
{
fprintf(stderr, "failed to getaddrinfo-ipv6: %s\n", gai_strerror(s));
return NULL;
}
return res;
}
int set_nonblock(int fd)
{
int flags = -1;
if(-1 == (flags = fcntl(fd, F_GETFL, 0)))
{
return -1;
}
flags |= O_NONBLOCK;
if( fcntl(fd, F_SETFL, flags) == -1 )
{
return -1;
}
return 0;
}
int tcpipv4_createfd_bind(struct addrinfo* rp)
{
int flags = -1;
int s;
// create socket
int sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
//assert(sfd!=-1);
if (sfd == -1)
{
fprintf(stderr, "failed to create socket\n");
return -1;
}
// bind
s = bind(sfd, rp->ai_addr, rp->ai_addrlen);
//assert(s==0);
if(s!=0)
{
fprintf(stderr, "failed to bind socket %d\n", sfd);
return -1;
}
// nonblock
s = set_nonblock(sfd);
//assert(s != -1);
if (s == -1)
{
fprintf(stderr, "failed to set nonblocking socket %d\n", sfd);
return -1;
}
return sfd;
}
int writen(int fd, char * buf, size_t len)
{
char * cur = buf;
int n = -1;
while(len>0)
{
n = write(fd, cur, len);
if (n<=0)
{
if(errno == EINTR) continue;
else return -1;
}
len -= n;
cur += n;
}
return 0;
}
int readn(int fd, char* buf, size_t len)
{
char *cur = buf;
int n = -1;
while (len>0)
{
n = read(fd, cur, len);
if (n == -1)
{
if (errno == EINTR)
continue;
else break;
}
else if (n == 0)
break;
cur += n; len -= n;
}
return (int)(cur-buf);
}
void accept_handler(int efd, int listenfd)
{
struct epoll_event event;
int s;
while(1)
{
struct sockaddr in_addr;
socklen_t in_addrlen = sizeof(struct sockaddr);
int infd = -1;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
infd = accept(listenfd, &in_addr, &in_addrlen);
//assert(infd != -1);
if(infd == -1)
{
if(errno == EAGAIN || errno == EWOULDBLOCK)
;
else
perror("failed to accept\n");
return;
}
s = getnameinfo(&in_addr, in_addrlen,
hbuf, sizeof(hbuf),
sbuf, sizeof(sbuf),
NI_NUMERICHOST | NI_NUMERICSERV);
//assert(s == 0);
if(s == 0)
{
printf("Accept fd %d host %s port %s\n", infd, hbuf, sbuf);
s = set_nonblock(infd);
//assert(s!=-1);
event.data.fd = infd;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);
//assert(s != -1);
return;
}
}
return;
}
void read_handler(int efd, int fd)
{
//do sonething with buf.
int s = -1;
s=readn(fd, buf, sizeof(buf));
buf[s] = 0;
//printf("recv %d bytes: %s", s, buf);
if(s < 0)
{
close(fd);
if(-1 == epoll_ctl(efd, EPOLL_CTL_DEL, fd, NULL) )
fprintf(stderr, "failed to del event of %d\n", fd);
printf("close conection on fd %d", fd);
}
else if(s > 0)
{
//std::cout << buf << std::endl;
//do sonething with buf.
user_recv_handler(efd, fd, buf, s);
}
}
void write_handler(int efd, int fd)
{
writen(fd, buf, strlen(buf));
if(-1 == epoll_ctl(efd, EPOLL_CTL_DEL, fd, NULL) )
fprintf(stderr, "failed to del event of %d\n", fd);
// close(fd);
}
int main(int argc, char ** argv)
{
char* port = NULL;
int listenfd = -1;
struct addrinfo* hostaddr=NULL;
struct addrinfo* rp = NULL;
struct epoll_event event;
struct epoll_event * events, *cur_ev;
int efd = -1;
int num_ev = -1;
int s;
port = argv[1];
// get server ipv4 address by getaddrinfo
(rp = hostaddr = tcpipv4_getaddrinfo(port));
// create and bind listening socket
for(; rp; rp = rp->ai_next)
{
(listenfd = tcpipv4_createfd_bind(rp));
if(-1 == listenfd)
continue;
}
freeaddrinfo(hostaddr);
//assert(listenfd!=-1);
if(listenfd==-1)
exit(EXIT_FAILURE);
//start listening
(s = listen(listenfd, SOMAXCONN));
//assert(s!=-1);
if(s == -1)
exit(EXIT_FAILURE);
// create epoll
efd = epoll_create(MAXEVENTS);
//assert(efd != -1);
if(efd == -1)
exit(EXIT_FAILURE);
event.data.fd = listenfd;
// epoll: read, ET
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &event);
//assert(s!=-1);
if(s==-1)
exit(EXIT_FAILURE);
events = (struct epoll_event*)calloc(MAXEVENTS, sizeof(struct epoll_event));
// event loop;
while (1)
{
num_ev = epoll_wait(efd, events, MAXEVENTS, -1);
// for each active event:
while(num_ev--)
{
cur_ev = events+num_ev;
// close the fd if error (ERR) or hang up (HUP)
if(cur_ev->events & EPOLLERR ||
cur_ev->events & EPOLLHUP)
{
fprintf(stderr, "epoll get event error\n");
close(cur_ev->data.fd);
continue;
}
// one or more new connections (fd = listenfd)
else if(cur_ev->data.fd == listenfd)
{
accept_handler(efd, listenfd);
continue;
}
else if(cur_ev->events & EPOLLIN)
{
// since the registered event is EPOLLIN,
// here we have data on fd waiting for reading.
read_handler(efd, cur_ev->data.fd);
}
else if (cur_ev->events & EPOLLOUT)
{
write_handler(efd, cur_ev->data.fd);
}
}
}
free(events); events = NULL;
close(listenfd);
exit(EXIT_SUCCESS);
}
客户:
int connected_count=0;
int i=0;
struct timespec tstart={0,0}, tend={0,0};
clock_gettime(CLOCK_MONOTONIC, &tstart);
for(; i!=10000; i++)
{
int sockfd;
int portno = 4000;
ssize_t n;
struct sockaddr_in serveraddr;
struct hostent* server;
char hostname[] = "127.0.0.1";
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
printf("ERROR opening socket");
printf("error %d",errno);
test_function_killall(NULL);
return;
}
server = gethostbyname(hostname);
if(server == NULL)
{
fprintf(stderr,"ERROR, no such host as %s\n", hostname);
test_function_killall(NULL);
return;
}
bzero((char*)&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char*)server->h_addr, (char*)&serveraddr.sin_addr.s_addr, server->h_length);
serveraddr.sin_port = htons(portno);
if(connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
{
printf("ERROR connecting");
test_function_killall(NULL);
return;
}
else
{
std::cout << "active connections " << connected_count++ << std::endl;
}
set_nonblock(sockfd);
}
if(connected_count==10000)
{
printf("complete");
}
最佳答案
从这里开始:
从监听套接字注册中删除 EPOLLET
标志。你可能也想从客户端连接套接字中删除它。
将您的监听套接字设置为非阻塞,类似于客户端的方式从 accept
返回的连接套接字已设置。
监听套接字有各种边缘情况。我不确定,但是当 epoll_ctl 返回指示监听套接字已准备好连接时,您似乎没有完全耗尽接受队列。 (想一想:一个边缘触发器上的多个传入连接)。您可能会阻止接受和/或卡在 epoll_wait 上。
更新:
关于c - Epoll tcp 服务器在接受连接时停止运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53529855/
我正在本地编程应用程序,但是当我迁移到服务器时,使用此行出现解析错误: if(!is_array($data[array_keys($data)[0]])) 返回值: Parse error: syn
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 9 年前。 Improv
我已经开始尝试用 C++ 学习 Winsock,但我遇到了一些问题。我首先遵循 MSDN 上的 Winsock 示例(一个基本的客户端-服务器)。 http://msdn.microsoft.com/
我有一段使用 epoll 的代码,但它有问题。当我运行它时,它给出输出:服务器套接字()没问题......服务器绑定(bind)()没问题......3个4个接受:无效参数 我在 ubuntu lin
我正在寻找一种方法来接受 $_GET 变量作为文件路径,例如 - /page/test将转换为 page.php?page=test .我已经搜索过,但找不到任何可以帮助我的东西,因此我在这里问。 我
我想要一个只接受从 0 到 9 和减号的浮点数的正则表达式。 请帮忙。 最佳答案 ^[-+]?[0-9]*\.?[0-9]+$ ^ - 字符串开头 [-+]? - 0 或 1 符号指示符 [0-9]*
请问如何接受\r\n无需将其更改为 \\r\\n , 与 fgets . 我想让程序翻译 \r\n到换行符而不是将其打印为字符串。 当前代码: char buff[1024]; printf("Msg
我正在编写一个 Cocoa 应用程序,该应用程序需要在其 Dock 图标上接受已安装卷的滴落。它不是基于文档的;我打算将每个卷分派(dispatch)到 application:openFiles 中
我在 SQLite 中发现了这种意外行为。 SQLite 似乎接受 SQL 连接语法中的任意关键字。如果我不小心键入了 natural join 而不是 natural join,则会生成笛卡尔积。这
我在 Windows 窗体的同一个窗体上有一个 TreeView 和一个多行文本框。我有拖放设置,以便我可以将节点从 TreeView 拖到文本框并将文本插入文本框(这是有效的)。 我想增强这一点,以
我正在创建一棵类似于 D3 Layout Tree 的树并尝试绑定(bind)我的自定义 JSON 对象。切换树节点的代码如下。 function toggleAll(d) { if (d.c
所以,我希望能够向我的 DOB 字段发送空选项。 这是我的表单生成器: ->add('birthDate', DateType::class, array( 'widg
错误可以在这里看到:http://djaffry.selfip.com:8080/ 我希望索引页接受参数,无论是 mysite.com/search/param_here 或 mysite.com/?
我想知道标准 Scala 解析器组合器是否包含一个解析器,该解析器接受 Scala 语言本身也接受的相同标识符(如 Scala 语言规范第 1.1 节中所指定)。 StdTokenParsers 特征
我暂时使用以下行在我的 Android 手机上创建 ServerSocket: socketl = new ServerSocket(port, 0, InetAddress.getByName("1
今天早上刚刚发布了一个应用程序,我在所有可能的设备和模拟器上测试了它,但是当我从商店下载它时,应用程序在启动时崩溃。我在很多设备和iOS版本上测试过,但结果都是一样的: Incident Identi
我想要 5 个名字中最长的一个。我想我应该使用 compareTo() 方法或 length()? 输出必须是这样的: enter 5 names : Joey Mark Catherine Zach
抱歉,我不熟悉泛型,我可以创建一个如下所示的泛型类: public class InfoField { } 上面的类可以接受如下值: , User> 但是我可以有接受 map 对象作为值的类吗?
我想让一个单元格等于它上面的单元格。 当我写作时 =address(row()-1;column()) 它只是写入上面单元格的名称(例如,对于 B2,它写入 $B$1) 是否有一个函数可以输入地址并放
我正在使用Asm访问java字节码来获取方法信息。看来ClassReader类的accept方法是异步调用的,所以不可能立即获取方法信息。我该怎么办? 最佳答案 实际上,accept 方法是从您自己的
我是一名优秀的程序员,十分优秀!