How do I create a C# server that remote users can connect to?

I have been trying to create a server-client application through sockets and the Tcp protocol for a very long time. I start the server and clients on my computer, sending messages and the response from the server work correctly, but if the client is started by someone else, an exception is thrown that the waiting time is exceeded and the server did not give a response. What should I do? Below I attach the server and client code.

Сервер

        string hostName = Dns.GetHostName();
        IPHostEntry ipEntry = Dns.GetHostByName(hostName);
        IPAddress[] ipAdresses = ipEntry.AddressList;

        IPEndPoint ipEndPoint = 
             new IPEndPoint(IPAddress.Parse(ipAdresses[0].ToString()), 2017);

        Socket sListener = 
             new Socket(IPAddress.Parse(ipAdresses[0].ToString()).AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            sListener.Bind(ipEndPoint);
            sListener.Listen(10);

            while (true)
            {

                updateLog("Waiting for connection on [" + ipEndPoint + "]");

                Socket handler = sListener.Accept();
                updateLog("New user join the channel. [" + handler.LocalEndPoint + "]");

                string data = null;

                byte[] bytes = new byte[1024];
                int bytesRec = handler.Receive(bytes);

                data += Encoding.UTF8.GetString(bytes, 0, bytesRec);

                updateLog("Client[" + handler.LocalEndPoint + "]: " + data);

                // Отправка ответа клиенту.
                string reply = "Thanks for your query. We got it!";
                byte[] replyMSG = Encoding.UTF8.GetBytes(reply);
                handler.Send(replyMSG);

                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }

Клиент

byte[] bytes = new byte[1024];

        IPAddress serverIp = IPAddress.Parse("Тут IP компьютера");

        IPEndPoint ipEndPoint = new IPEndPoint(serverIp, port);
        Socket sender = new Socket(serverIp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

        sender.Connect(ipEndPoint);
        byte[] msg = Encoding.UTF8.GetBytes(msgTB.Text);
        int bytesSend = sender.Send(msg);
        int bytesRec = sender.Receive(bytes);

        logTB.AppendText("Server: " + Encoding.UTF8.GetString(bytes, 0, bytesRec));

        sender.Shutdown(SocketShutdown.Both);
        sender.Close();
Author: kos channel, 2017-03-03

2 answers

Here's how the server should look like...

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpListener serverSocket = new TcpListener(8888);
            TcpClient clientSocket = default(TcpClient);
            int counter = 0;

            serverSocket.Start();
            Console.WriteLine(" >> " + "Server Started"); 

            counter = 0;
            while (true)
            {
                counter += 1;
                clientSocket = serverSocket.AcceptTcpClient();
                Console.WriteLine(" >> " + "Client No:" + Convert.ToString(counter) + " started!");
                handleClinet client = new handleClinet();
                client.startClient(clientSocket, Convert.ToString(counter));
            }

            clientSocket.Close();
            serverSocket.Stop();
            Console.WriteLine(" >> " + "exit");
            Console.ReadLine();
        }
    }

    //Class to handle each client request separatly
    public class handleClinet
    {
        TcpClient clientSocket;
        string clNo;
        public void startClient(TcpClient inClientSocket, string clineNo)
        {
            this.clientSocket = inClientSocket;
            this.clNo = clineNo;
            Thread ctThread = new Thread(doChat);
            ctThread.Start();
        }
        private void doChat()
        {
            int requestCount = 0;
            byte[] bytesFrom = new byte[10025];
            string dataFromClient = null;
            Byte[] sendBytes = null;
            string serverResponse = null;
            string rCount = null;
            requestCount = 0;

            while ((true))
            {
                try
                {
                    requestCount = requestCount + 1;
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    Console.WriteLine(" >> " + "From client-" + clNo + dataFromClient);

                    rCount = Convert.ToString(requestCount);
                    serverResponse = "Server to clinet(" + clNo + ") " + rCount;
                    sendBytes = Encoding.ASCII.GetBytes(serverResponse);
                    networkStream.Write(sendBytes, 0, sendBytes.Length);
                    networkStream.Flush();
                    Console.WriteLine(" >> " + serverResponse);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(" >> " + ex.ToString());
                }
            }
        }
    } 
}

And here is a possible implementation of the client...

using System;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Text; 

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
        NetworkStream serverStream; 

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            msg("Client Started");
            clientSocket.Connect("127.0.0.1", 8888);
            label1.Text = "Client Socket Program - Server Connected ...";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            NetworkStream serverStream = clientSocket.GetStream();
            byte[] outStream = System.Text.Encoding.ASCII.GetBytes("Message from Client$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();

            byte[] inStream = new byte[10025];
            serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
            string returndata = System.Text.Encoding.ASCII.GetString(inStream);
            msg("Data from Server : " + returndata);
        }

        public void msg(string mesg)
        {
            textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + mesg;
        } 
    }
}
 1
Author: Денис Шевелев, 2017-03-07 04:22:47

To implement your task, I advise you to turn to SOA, namely to the WCF technology (https://msdn.microsoft.com/ru-ru/library/ms731082(v=vs. 110).aspx).

This is an advanced technology from Microsoft, which hides most of the tinsel associated with RPC from the developer, as well as provides unprecedented flexibility and scalability.

Very useful video tutorials on WCF can be found here https://itvdn.com/ru/video/wcf-essential

 0
Author: Exodium, 2017-03-10 09:17:54