mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* TCP connections come in wrong order
@ 2015-02-01 21:30 Askar Safin
  2015-02-02 15:07 ` One Thousand Gnomes
  0 siblings, 1 reply; 2+ messages in thread
From: Askar Safin @ 2015-02-01 21:30 UTC (permalink / raw)
  To: linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=utf-8, Size: 4539 bytes --]

Consider the following code:

// C99, No error checking for simplicity

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>

#include <err.h>

static int
tcp_connect_loop (const char *host, const char *protocol, struct addrinfo *res)
{
  for (; res != NULL; res = res->ai_next)
    {
      int result = socket (res->ai_family, res->ai_socktype, res->ai_protocol);

      if (result != -1)
        {
          if (connect (result, res->ai_addr, res->ai_addrlen) == 0)
            {
              return result;
            }

          close (result);
        }
    }

  // SOMEDAY: печатать больше инфы (то же для tcp_listen_loop)?
  errx (EXIT_FAILURE, "sh_tcp_connect: [%s]:%s: all structs returned by getaddrinfo failed", host, protocol);
}

int //@
sh_tcp_connect (const char *host, const char *protocol, int family)//@;
{
  struct addrinfo hints = {};

  hints.ai_family = family;
  hints.ai_socktype = SOCK_STREAM;

  struct addrinfo *res;

  getaddrinfo (host, protocol, &hints, &res);

  // POSIX 2013 says that now 'res' list contains at least one item

  int result;

      result = tcp_connect_loop (host, protocol, res);
      freeaddrinfo (res);

  return result;
}


static int
tcp_listen_loop (const char *protocol, struct addrinfo *res)
{
  for (; res != NULL; res = res->ai_next)
    {
      int result = socket (res->ai_family, res->ai_socktype, res->ai_protocol);

      if (result != -1)
        {
          const int on = 1;

          if (setsockopt (result, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != -1)
            {
              if (bind (result, res->ai_addr, res->ai_addrlen) == 0)
                {
                  return result;
                }
            }

          close (result);
        }
    }

  errx (EXIT_FAILURE, "sh_tcp_listen: *:%s: all structs returned by getaddrinfo failed", protocol);
}

int //@
sh_tcp_listen (const char *protocol, int family)//@;
{
  struct addrinfo hints = {};

  hints.ai_flags = AI_PASSIVE;
  hints.ai_family = family;
  hints.ai_socktype = SOCK_STREAM;

  struct addrinfo *res;

  getaddrinfo (NULL, protocol, &hints, &res);

  int result;

      result = tcp_listen_loop (protocol, res);

          listen (result, 5);
      freeaddrinfo (res);
  return result;
}

#ifndef N
#define N 100000
#endif

int
main (int argc, char *argv[])
{
  if (strcmp (argv[1], "-l") == 0)
    {
      int l = sh_tcp_listen (argv[2], AF_INET);

      for (;;)
        {
          int s = accept (l, NULL, NULL);
          if (s == -1)
            {
              continue;
            }
          char buf[1000];
          write (1, buf, read (s, buf, sizeof (buf)));
          close (s);
        }
    }
  else
    {
      for (int i = 0; i != N; ++i)
        {
          int s = sh_tcp_connect (argv[1], argv[2], AF_INET);
          dprintf (s, "%d\n", i);
          close (s);
        }
    }
  exit (EXIT_SUCCESS);
}

Compile this code as, for example, /tmp/x (again: this is C99), then run:

/tmp/x -l 5555 > /tmp/ooo

This command will accept connections and write coming data to /tmp/ooo . Okey, then run in another terminal:

/tmp/x localhost 5555

This command will connect to localhost, write 0, then connect again, write 1, etc. Soon you will not have available ports, so /tmp/x will fail before it will perform all N connections, this is OK.
When this command complete, go to the first terminal and kill the program using Ctrl-C. Then look in /tmp/ooo and notice the last line, let's assume this is 28290. Then compare /tmp/ooo with the right monotonic number sequence:

echo {0..28290} | tr ' ' '\n' | diff -ur - /tmp/ooo

With some luck you will notice that /tmp/ooo is wrong. For example, I got the following:

--- -   2015-02-02 00:24:35.606008461 +0300
+++ /tmp/ooo    2015-02-02 00:09:25.002694629 +0300
@@ -7391,8 +7391,6 @@
 7390
 7391
 7392
-7393
-7394
 7395
 7396
 7397
@@ -7546,6 +7544,8 @@
 7545
 7546
 7547
+7393
+7394
 7548
 7549
 7550

If 'diff' doesn't report difference, then try again and again.

Is this a bug? I think that this is a bug.

Linux ideal-os 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt2-1 (2014-12-08) x86_64 GNU/Linux
Debian 8.0 Jessie
GNU C Library (Debian GLIBC 2.19-13) stable release version 2.19, by Roland McGrath et al.
==
Askar Safin
http://vk.com/safinaskar
Kazan, Russiaÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: TCP connections come in wrong order
  2015-02-01 21:30 TCP connections come in wrong order Askar Safin
@ 2015-02-02 15:07 ` One Thousand Gnomes
  0 siblings, 0 replies; 2+ messages in thread
From: One Thousand Gnomes @ 2015-02-02 15:07 UTC (permalink / raw)
  To: Askar Safin; +Cc: linux-kernel

> If 'diff' doesn't report difference, then try again and again.
> 
> Is this a bug? I think that this is a bug.
> 
> Linux ideal-os 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt2-1 (2014-12-08) x86_64 GNU/Linux
> Debian 8.0 Jessie
> GNU C Library (Debian GLIBC 2.19-13) stable release version 2.19, by Roland McGrath et al.
> ==

No it's not a bug. Nothing in SuS or traditional BSD sockets guarantees
that connections are processed in strict time sequenced incoming order.

Alan

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-02-02 15:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-01 21:30 TCP connections come in wrong order Askar Safin
2015-02-02 15:07 ` One Thousand Gnomes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®