1

Currently, I'm programming in C#, I would like to modify the code below to isolate one client connection. so like creating a break-out room from the main pool.

Below are 2 files, one is just the basic standard .NET Framework Console App Program.cs file; the other is the server file. Combined, they both can make a multi-threaded server, but I would like one that allows me to also select a client to connect to in case if I were to create a remote control application as my friend did.

On a side note, I would like to share that I want to be able to connect to a client by entering connect [1,2,3,etc..] into the console.

Answers

If you answer, please put some code, It would really, really help. I learn a lot better by looking att the code rather than reading documentation.

Code

Server.cs

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace TCPServer
{
    class Server
    {
        TcpListener server = null;
        int counter = 0;
        public Server(string ip, int port)
        {
            IPAddress localAddr = IPAddress.Parse(ip);
            server = new TcpListener(localAddr, port);
            server.Start();
            StartListener();
        }
        public void StartListener()
        {
            try
            {
                while (true)
                {
                    Console.WriteLine("Waiting for incoming connections...");
                    TcpClient client = server.AcceptTcpClient();
                    counter += 1;
                    Console.WriteLine("Connected to authorized client: {0}", counter);
                    Thread t = new Thread(new ParameterizedThreadStart(HandleDeivce));
                    t.Start(client);
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
                server.Stop();
            }
        }
        public void HandleDeivce(Object obj)
        {
            TcpClient client = (TcpClient)obj;
            var stream = client.GetStream();
            string imei = String.Empty;
            string data = null;
            Byte[] bytes = new Byte[256];
            int i;
            try
            {
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    string hex = BitConverter.ToString(bytes);
                    data = Encoding.ASCII.GetString(bytes, 0, i);
                    Console.WriteLine("{1}: Received: {0}", data, Thread.CurrentThread.ManagedThreadId);
                    if (data != "auth token")
                    {
                        stream.Close();
                        client.Close();
                    }

                    string str = "Device authorization successfull";
                    Byte[] reply = System.Text.Encoding.ASCII.GetBytes(str);
                    stream.Write(reply, 0, reply.Length);
                    Console.WriteLine("{1}: Sent: {0}", str, Thread.CurrentThread.ManagedThreadId);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.ToString());
                client.Close();
            }
        }
    }
}

Program.cs

using System;
using System.Threading;

namespace TCPServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread thread = new Thread(delegate()
            {
                Server server = new Server("127.0.0.1", 13000);
            });
            thread.Start();

            Console.WriteLine("Server started...");
        }
    }
}
Ridley Nelson
  • 43
  • 1
  • 7
  • A client/server has two meanings depending if are at the application layer or the socket layer. You are using TCP which is the socket layer. With TCL the server (listener) must be started first and then you connect the client to the listener. In Net the listener is automatically configured to allow multiple clients to connect. At the application layer you can have a two port server where one port is a listener and the other port a client. – jdweng Jan 13 '21 at 17:27
  • alright, how would I implement this? I'm sort of a newbie-ish in socket programming with C#, however, when it comes to Python3 and Java I'm fine. – Ridley Nelson Jan 13 '21 at 17:48
  • You client IP address is a string to just change the string to a different IP : Server(string ip, int port). You only posted TCP listener code and not client. – jdweng Jan 13 '21 at 17:51
  • I get that, but the part about hosting on 2 different ports? would I just create 2 instances of Server but with different ports? – Ridley Nelson Jan 13 '21 at 17:53
  • That will work. But normally you would have one client and one server. Suppose you have a service that took clients queries to a database. You would start the service by opening a client to the database. Then start listening for clients connecting and processing queries. – jdweng Jan 13 '21 at 17:59
  • Yeah, i was just looking at a StackOverflow question saying to usesomething like that. it includes: `Dictionary clintlist= new Dictionary();`. I don't mean to ask too much of you, but can you tell me how I would implement this? code would be helpful – Ridley Nelson Jan 13 '21 at 18:08
  • Look at the MSDN Async Server. The accept method the "ar" is the socket from the client. So in the accept method you can add the TCPClient (a socket) to your dictionary : https://learn.microsoft.com/en-us/dotnet/framework/network-programming/socket-code-examples. I think you would want Dictionary although you can cast a socket to a client since the client.client property is a socket (yes two clients). – jdweng Jan 13 '21 at 18:21
  • thanks, I'll take a look. so..what you're saying is that I could essentially put `client` from `HandleDevice` in the dictionary because it's the client's socket? and once I need it again, I just somehow look for it? – Ridley Nelson Jan 13 '21 at 18:29
  • The socket remote endpoint is the IP. So in the accept method add to dictionary. Then send back to the same socket. I did something similar here : https://stackoverflow.com/questions/44471975/gps-socket-communication-concox/44673435 – jdweng Jan 13 '21 at 18:39
  • alright, I think I got enough to have a strong base to reprogram this. Thank you very much! I also found another post [here](https://stackoverflow.com/questions/39644401/how-to-handle-multiple-active-connections-in-a-tcp-c-sharp-socket-server) that I think might come in handy. – Ridley Nelson Jan 13 '21 at 18:47
  • I don't like that example because of the sleep. My preference is to use the async listener. Also don't think that code works. There is only one client and you need a client for each remote connection. I don't trust an answer that says "something like this". – jdweng Jan 13 '21 at 18:53
  • could you possibly provide a working solution? if posting an answer doesn't suit you, you could just send a GitHub gist. – Ridley Nelson Jan 13 '21 at 19:02
  • See my link above. My code does very similar to what you need. Look at the Accept method. The write to dictionary is in the Read/Write method : Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Create the state object. StateObject state = ReadWrite(PROCESS_STATE.ACCEPT, handler, ar, - 1).Value; handler.BeginReceive(state.buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state); – jdweng Jan 13 '21 at 22:17
  • thanks, I took the ReadWrite function and changed most of it to fit my application. so far it's working. I found out how to write the async Accept method yesterday from the Microsoft docs, so I'm using that. – Ridley Nelson Jan 14 '21 at 20:07

0 Answers0