【发布时间】:2014-10-13 22:00:19
【问题描述】:
我有一个使用 Unix 域套接字实现的客户端和一个服务器。
我想看看客户端可以在服务器不读取数据的情况下将多少数据推送到套接字。我希望客户端能够在被阻止之前发送大约 20-30KB 的数据。我检查了 net.core.rmem_default、net.core.wmem_default、net.core.rmem_max、net.core.wmem_max 和 net.unix.max_dgram_qlen sysctl 选项,并确定我没有达到这些值。我还增加了 net.unix.max_dgram_qlen 值,但似乎没有帮助。
看到我能够发送的固定大小的消息数量约为 138 条,我感到非常惊讶。即使我减小了消息的大小,这个数字仍然保持不变。
在客户端,我进入一个循环并写入 1024 条消息。
客户代码
void write_text (int socket_fd, char* text)
{
int length = strlen (text) + 1;
send (socket_fd, &length, sizeof (length),0);
/* Write the string. */
send (socket_fd, text, length,0);
}
int main (int argc, char* const argv[])
{
const char* const socket_name = argv[1];
char message[100];
int socket_fd;
int loop = 0;
struct sockaddr_un name;
/* Create the socket. */
socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
/* Store the server's name in the socket address. */
name.sun_family = AF_UNIX;
strcpy (name.sun_path, socket_name);
/* Connect the socket. */
connect (socket_fd, (struct sockaddr *) &name, SUN_LEN (&name));
for (loop=0;loop<1024;loop++)
{
sprintf (message, "message number %d coming from the client", loop);
/* Write the text on the command line to the socket. */
write_text (socket_fd, message);
}
close (socket_fd);
return 0;
}
服务器端代码:
unsigned int global_flag = 0;
int client_socket_fd = 0;
int server (int client_socket)
{
while (1)
{
int length;
char* text;
if (read (client_socket, &length, sizeof (length)) == 0)
return 0;
text = (char*) malloc (length);
read (client_socket, text, length);
printf ("length %d %s\n", length, text);
if (global_flag<5) break;
free (text);
}
return 0;
}
int main (int argc, char* const argv[])
{
const char* const socket_name = argv[1];
int socket_fd;
struct sockaddr_un name;
int client_sent_quit_message;
socklen_t socket_length = sizeof(struct sockaddr_un);
int result;
int len = sizeof (int);
int data = 0;
socket_fd = socket (AF_LOCAL, SOCK_STREAM, 0);
name.sun_family = AF_UNIX;
strcpy (name.sun_path, socket_name);
socket_length = strlen(name.sun_path) + sizeof (name.sun_family);
bind (socket_fd, (struct sockaddr *) &name, socket_length);
listen (socket_fd, 5);
while (1)
{
struct sockaddr_un client_name;
socklen_t client_name_len;
/* Accept a connection. */
client_socket_fd = accept (socket_fd, (struct sockaddr *) &client_name, &client_name_len);
client_sent_quit_message = server (client_socket_fd);
}
/* Remove the socket file. */
close (socket_fd);
unlink (socket_name);
return 0;
}
在服务器端代码中,global_flag 始终小于 0,因此服务器执行一次读取并输出。服务器不再进行读取。客户端同时在套接字上推送数据。
我在客户端上做了一个 strace 并得到了这个:
VirtualBox:~/code/linux$ strace ./unix-client /tmp/unixtest
execve("./unix-client", ["./unix-client", "/tmp/unixtest"], [/* 44 vars */]) = 0
brk(0) = 0x1245000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3e12b63000
fstat(3, {st_mode=S_IFREG|0644, st_size=68001, ...}) = 0
mmap(NULL, 68001, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3e12b52000
close(3) = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=1815224, ...}) = 0
mmap(NULL, 3929304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f3e12583000
[clipped]
socket(PF_FILE, SOCK_STREAM, 0) = 3
connect(3, {sa_family=AF_FILE, path="/tmp/unixtest"}, 15) = 0
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 0 coming from the"..., 40, 0, NULL, 0) = 40
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 1 coming from the"..., 40, 0, NULL, 0) = 40
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 2 coming from the"..., 40, 0, NULL, 0) = 40
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
..
sendto(3, "message number 138 coming from t"..., 42, 0, NULL, 0) = 42
sendto(3, "*\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 139 coming from t"..., 42, 0, NULL, 0) = 42
sendto(3, "*\0\0\0", 4, 0, NULL, 0
[和这里的客户块]
知道为什么当服务器停止从套接字排出消息时客户端在发送 139 条消息后会被阻塞?
我假设如果我减小消息的大小,客户端可以在套接字上发送的消息数量会增加。但是,我看到它保持不变。无论消息的大小如何,客户端都无法在套接字上发送超过 139 条消息而不会被阻塞。
【问题讨论】:
-
问题是?
-
只是一个注释,实际上与您的问题无关:
sizeof是一个运算符,而不是一个函数。sizeof的参数应该是变量、表达式或带括号的类型名称。所以在你有sizeof (length)的两个地方,它真的应该是sizeof length,或者sizeof (int)。 -
问题是为什么客户端在发送139条消息后不管消息的大小都会被阻塞。这个限制来自哪里?