リッスン バックログの制限をテストしようとしています。私は数日間、これに関する情報を収集しています。listen() に提供されるバックログ数は単なるヒントであることはわかっています。しかし今、バックログの制限をテストするために、サーバーとクライアント (TCP を使用) を作成しようとしています。
私のサーバーでは、connect()、bind()、listen()、そして sleep() を長時間使用しています。私のクライアントでは、fdsock を作成して connect() を使用するループを使用しています。
サーバーは何も受け入れていないので、接続はバックログキューに送られますが、1000 以上の sockfd を作成した後でも、プログラムは停止しません。
バックログ キューの最大制限をテストする方法はありますか?
事前に感謝します。
編集:
#include "sys.h"
char *answer(char *port, int (*fun)(int)){
struct addrinfo * info, * p, indices;
struct sockaddr fromaddr;
int fd, t, toclient;
unsigned int len = sizeof fromaddr;
memset(&indices, 0, sizeof indices);
indices.ai_flags = AI_PASSIVE;
indices.ai_family = AF_INET;
indices.ai_socktype = SOCK_STREAM;
t = getaddrinfo(0, port, &indices, &info);
if(t != 0)
{
return "answer: cannot get info on port";
}
for(p = info; p != 0; p = p->ai_next)
{
fd = socket(p->ai_family, p->ai_socktype, 0); // fabriquer la socket
if(fd >= 0)
{
break;
}
}
if(p == 0)
{
return "answer: cannot open socket";
}
t = 1;
t = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof t);
if(t < 0)
{
perror("setsockopt");
}
if(bind(fd, p->ai_addr, p->ai_addrlen) < 0)
{
close(fd);
return "answer: cannot bind socket";
}
freeaddrinfo(info);
t = listen(fd, 1);
if(t < 0)
{
close(fd);
return "answer: cannot listen on socket";
}
for(;;)
{
toclient = accept(fd, &fromaddr, &len);
sleep(600);
if(toclient < 0)
{
return "answer: cannot accept\n";
}
t = fork();
if(t < 0) // error
{
perror("fork");
continue;
}
else if(t != 0) // parent
{
close(toclient);
}
else // child
{
close(fd);
fun(toclient);
exit(0);
}
}
}
int foo(int n){
char c;
int t;
printf("I have a new client\n");
while((t = read(n, &c, 1)) > 0)
{
if(write(n, &c, 1) != 1)
{
perror("write");
break;
}
}
if(t < 0)
{
perror("read");
}
printf("I don't have that client anymore\n");
return 0;
}
int main(int argc, char *argv[]){
char *p;
p = answer(argv[1], foo);
perror(p);
return 1;
}
そして、これが私のクライアントのコードです:
# include "sys.h"
int dial(char *machine, char *port){
struct addrinfo *info, *p, indices;
int toserver, t;
memset(&indices, 0, sizeof indices);
indices.ai_family = AF_INET;
indices.ai_socktype = SOCK_STREAM;
t = getaddrinfo(machine, port, &indices, &info);
if(t != 0)
{
return -1;
}
for(p = info; p != 0; p = p->ai_next)
{
toserver = socket(p->ai_family, p->ai_socktype, 0);
if(toserver >= 0)
{
break;
}
}
if(p == 0)
{
return -1;
}
t = connect(toserver, info->ai_addr, info->ai_addrlen);
if(t < 0)
{
freeaddrinfo(info);
close(toserver);
return -1;
}
freeaddrinfo(info);
return toserver;
}
int main(int argc, char *argv[]){
char buffer[1];
int t, fd = dial(argv[1], argv[2]);
while((t = read(0, buffer, sizeof buffer)) > 0)
{
write(fd, buffer, t);
t = read(fd, buffer, sizeof buffer);
write(1, buffer, t);
}
return 0;
}
バックログの長さを 1 に設定し、サーバーを長時間スリープ状態にして、いくつかのクライアントを起動しようとしましたが、何百ものクライアントを起動しても決して拒否されません。