3

I am trying to manage a client side in a chat program. So the client should get the input from the keyboard and send it to the server. In the meantime, it should be able to recieve masseges from the server.

In C, we have the select() function, and in linux stdin has a file descriptor, so I could use select() to get indicated when stdin or the socket is ready for read.

My question:

  • How can I do it in C# and windows? Socket.Select() accepts only Sockets, but the StandardInput is a stream. How could I use it in Select()?
  • I know I can use another thread to monitor the stdin, but I'm looking for a sulution that handle it in one thread.

that is what I'm trying to do, in general:

        public void Run()
        {
            clientSide.Connect(ipEndPoint);
            //-> make a Socket for stdin:
            //-> Socket stdinSocket = new Socket(????);
            List<Socket> checkReadList = new List<Socket>();
            checkReadList.Add(clientSide);
            checkReadList.Add(stdinSocket);

            while (CanRun())
            {
                Socket.Select(checkReadList, null, null, -1);
                foreach(Socket current in checkReadList)
                {
                     if(stdinSocket == current)
                     {
                         Console.ReadLine(.....);
                         ....
                     }
                     if (clientSide == current)
                     {
                         SendMessageToServer(...);
                     } 
            }
        }

Thanks!

Niro
  • 43
  • 3
  • You can use `NetworkStream` to wrap a `Socket`, could you change the logic of your program to leverage `Stream`s instead of `Socket`s? – Matthew May 27 '21 at 10:05
  • 1
    @Matthew but then the problem remains: how to monitor 2 streams from one thread – Marc Gravell May 27 '21 at 10:06
  • 1
    Fundamentally, I'd challenge *why* you are trying to do it this way; if this was me, I'd be using async reads on (separately) the socket and stdin - and *zero* of *my* threads (using the thread-pool for IO callbacks etc); what are you trying to gain by using `Socket.Select` here? – Marc Gravell May 27 '21 at 10:08
  • @MarcGravell I'll be honest I'm not sure why OP wants their solution to be single threaded, but they could alternate between the streams in the loop, potentially using a `StreamReader` to `Peek` if data is available before blocking. I agree that async makes the most sense here, but I am unsure of how strict OP is in terms of thread usage. – Matthew May 27 '21 at 10:26
  • @MarcGravell. The client always listens to the server and also to stdin, which means it happens _in a loop_. So how can I use the `async read` in a loop, when maybe it's just one of the streams ready to read in each iteration? – Niro May 27 '21 at 10:42
  • @Niro I understrand the setup; I'm just saying that you're going about this the wrong way. I get it that you're thinking about this as a single loop - I'm saying "don't do that"; it is IMO better to listen to both sources asynchronously and then either synchronize (i.e. `lock` etc) while you process results (so you're never dealing with concurrency), or have both async readers push data into a suitable mechanism such as a `Channel`, and have a single reader loop that processes *that* (which can also be async, for that zero-thread-goodness) – Marc Gravell May 27 '21 at 10:54
  • But to answer the question explicitly: no, you can't use `Socket.Select` with stdin; nor is there a convenient "read from two streams, let me know when you get data from either" API – Marc Gravell May 27 '21 at 10:55

0 Answers0