I made some network application. It is a client-server solution using the TCP/IP protocol. Clients connect to the server. They make several connections every second. Communication consists of units of bytes that are read and written interleaved several hundred times in each connection. And here is a problem in my application. As the connection length (in bytes) increases, communication becomes unbearably slow (one request lasts 5 seconds). I think the problem is with interleaving reading and writing of short pieces of data (about 8 bytes).
My program looks like this:
fd = socket(AF_INET, SOCK_STREAM, 0);
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, (socklen_t)sizeof(reuse)) < 0) {
// ...
}
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&reuse, (socklen_t)sizeof(reuse)) < 0) {
// ...
}
init_sockaddr(&server_addr, serverport);
if (bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
// ...
}
if (listen(fd, 2048) < 0) {
// ...
}
while (1) {
int cl_fd = accept(fd, &sockaddr_in, &sockaddr_len);
if (read_message(cl_fd, 0, ipv4) < 0) {
// ...
}
}
In the read_message
function, the problematic code is something like this:
if (write_uint64(fd, n) < 0) {
// ...
}
if (write_uint64(fd, TASK_SIZE) < 0) {
// ...
}
if (read_uint64(fd, &clid) < 0) {
// ...
}
The write_uint64
sends 8 bytes, whereas read_uint64
receives 8 bytes.
This code is typically repeated 128 times in a function for one connection.
My question is why interleaving reading and writing small pieces of data slows me down so much?
Is turning on TCP_NODELAY
a bad idea?
What should be set on the TCP/IP connection so that writes and reads do not wait?
The full code is available here.
root
access to the server?tcpdump
and compare the time between an incoming packet and its response packet. If this time changes with the amount of data per connection then the problem is on the server. It it does not then some network node does not like this traffic.