0

So I've created a "simple chat app" that works in LAN, but when i try to go outside the LAN it does not work. I've been searching the net for solution and came across lots of stuff, like NAT traversal, port forwarding and so on...None of which i found useful. My question is: How to make my app work across the WAN? I understand that what I want is for 2 PC's to communicate with each other over the internet (one will be client, and the other one will simulate server), and that those PC's are hidden behind routers that use NAT. But i don't know how to make my app work.

SERVER:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Net.Sockets;

namespace sukaServer
{
    public partial class Form1 : Form
    {
        Socket sock;
        Socket accept;
        public Form1()
        {
            InitializeComponent();
        }

        Socket socket()
        {
            return new Socket(AddressFamily.InterNetwork, SocketType.Stream,     ProtocolType.Tcp);
    }

    private void buttonListenServ_Click(object sender, EventArgs e)
    {
        sock = socket();
        sock.Bind(new IPEndPoint(0, 80));
        sock.Listen(0);

        new Thread(delegate ()
        {
            accept = sock.Accept();
            MessageBox.Show("CONNECTED!");
            sock.Close();

            while (true)
            {
                try
                {
                    byte[] buffer = new byte[255];
                    int rec = accept.Receive(buffer, 0, buffer.Length, 0);

                    if (rec <= 0)
                    {
                        throw new SocketException();
                    }

                    Array.Resize(ref buffer, rec);

                    Invoke((MethodInvoker)delegate
                    {
                        listBoxServer.Items.Add(Encoding.Default.GetString(buffer));
                    });
                }
                catch
                {
                    MessageBox.Show("DISCONNECTED!");
                    sock.Close();
                    break;
                }
            }
            Environment.Exit(0);
        }).Start();
    }

    private void buttonServerSend_Click(object sender, EventArgs e)
    {
        byte[] data = Encoding.Default.GetBytes(textBoxServerSend.Text);
        accept.Send(data, 0, data.Length, 0);
        textBoxServerSend.Clear();
    }
}
}

CLIENT:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace suka
{
    public partial class Form1 : Form
    {
        Socket sock;
        Socket socket()
        {
        return new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
    public Form1()
    {
        InitializeComponent();
        sock = socket();
        FormClosing += new FormClosingEventHandler(Form1_FormClosing);
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        sock.Close();
    }

    private void buttonClientConnect_Click(object sender, EventArgs e)
    {
        try
        {
            sock.Connect(new IPEndPoint(IPAddress.Parse(textBoxClientConnect.Text), 80));
            new Thread(delegate ()
            {
                read();
            }).Start();
        }
        catch
        {
            MessageBox.Show("CANNOT CONNECT!");
        }
    }

    void read()
    {
        while (true)
        {
            try
            {
                byte[] buffer = new byte[255];
                int rec = sock.Receive(buffer, 0, buffer.Length, 0);

                if (rec <= 0)
                {
                    throw new SocketException();
                }

                Array.Resize(ref buffer, rec);

                Invoke((MethodInvoker)delegate
                {
                    listBoxClient.Items.Add(Encoding.Default.GetString(buffer));
                });
            }
            catch
            {
                MessageBox.Show("DISCONNECTED!");
                sock.Close();
                break;
            }
        }
        Environment.Exit(0);
    }


    private void buttonClientSend_Click(object sender, EventArgs e)
    {
        byte[] data = Encoding.Default.GetBytes(textBoxClientSend.Text);
        sock.Send(data, 0, data.Length, 0);
        textBoxClientSend.Clear();
    }
}
}

I know that this will smell like a duplicate on the first sight, but none of the posts i saw addressed the SAME EXACT issue, either they want A and B to communicate through a server, or something else. I want A and B chatting, where A is the server, and B is the client or vice versa. And the first thing I want is to make it able to work on internet, later I will address the async issue.

EDIT: Lemme just clarify the "not working" thing.... It throws the exception that im catching and goes through ("CANNOT CONNECT!") part of code.

  • You're using port 80? Not sure that's the best port range to be in. – pay Apr 29 '16 at 16:49
  • Oh, that's just last port i tried, i tried a dozen others, like 8080, 20000 and so on... – MilanMarkovicDrmr Apr 29 '16 at 16:51
  • Yes I would generally try to use something in the much higher range, 20,000+, as many of the lower ports (<2000) are in the "reserved" range. Also, you should be putting that exception into a variable (i.e. `catch(Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.InnerException); }` And see what the specific exception is. I would also suggest making sure both applications are running as Administrator or the port is open on the respective machines. I would guess that you may see `The target machine actively refused the connection`. – pay Apr 29 '16 at 16:55
  • @user1438893 if you mean run as admin because of firewall issue, that's not it, BIND() makes sure that admin permission is necessary for communication, so i guess dat leaves the exception reading part ;/ ( i don't think it will help :P) – MilanMarkovicDrmr Apr 29 '16 at 17:03
  • Well of course it will help. That is the basis of debugging a program. You catch the exception, see what the exception is, and address the specific error. You cannot debug without viewing exception details. Otherwise you are just blindly guessing and stabbing in the dark. – pay Apr 29 '16 at 17:40

1 Answers1

0

If both machines are behind a NAT, you will need to configure port forwarding on atleast one of the nodes. Many home-routers can do this dynamically by using the uPnP protocol without logging into the router.

Stian Skjelstad
  • 2,277
  • 1
  • 9
  • 19