-1

I am trying to use sockets to send messages to computers, but I keep getting this error:

System.NullReferenceException: 'Object reference not set to an instance of an object.'
sw was null.

This is my code:

public partial class ServerGUI : Form
{
    Socket soc;
    StreamReader sr;
    StreamWriter sw;
    Stream s;
    public ServerGUI()
    {
        InitializeComponent();
        try
        {
            if (Server.port == 0)
            { }
            else
            {
                textBox2.Text = Server.port.ToString();
            }

        }
        catch (Exception) { }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        connect();
    }
    void connect()
    {
        Server.port = int.Parse(textBox2.Text);
        TcpListener listener = new TcpListener(IPAddress.Any, Server.port);
        listener.Start();
        soc = listener.AcceptSocket();
        s = new NetworkStream(soc);
        sr = new StreamReader(s);
        sw = new StreamWriter(s);
        sw.AutoFlush = true; // enable automatic flushing
        if (soc.Connected == true)
        {
            Console.WriteLine("Connected");
            sw.WriteLine("Server Connected");
        }
        this.Hide();
        Menu menu = new Menu();
        menu.Show();
    }
    void recieve()
    {
        Console.WriteLine(sr.ReadLine());
    }
    public void close()
    {
        s.Close();
        soc.Disconnect(true);
        Menu menu = new Menu();
        menu.Close();
        this.Show();
    }
    public void send(string msg)
    {
        sw.WriteLine(msg);
    }

This is the code for the button:

ServerGUI sgui = new ServerGUI();
public Menu()
{
    InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    sgui.close();
}

private void button2_Click(object sender, EventArgs e)
{
    sgui.send(textBox1.Text);
}

The writeline code in the connect method works but the code in the send method doesn't. I have tried this question: What is a NullPointerException, and how do I fix it? but it has not helped me. Thanks

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • 2
    Show how you call the `send` and `connect`. And, did you debug?.. – Gilad Green Sep 03 '17 at 06:35
  • 3
    If you genuinely cannot track down the null pointer from the other question and answer, you need to present an [mcve]. Just showing us two fragments and assuring us that the program is correctly structured to ensure no nulls are not enough (especially since, if that were the case, you wouldn't be having the null reference - clearly your assumptions are currently incorrect) – Damien_The_Unbeliever Sep 03 '17 at 06:44
  • And where do you call the `send`? – Gilad Green Sep 03 '17 at 06:48
  • 1
    Looking at these two lines in `close`: `Menu menu = new Menu(); menu.Close();` makes me suspect that you're making the mistake of creating *new* instances of forms when what you actually want/need to do is to pass instances around so that forms can interact with each other. So the `sgui` you're creating in the second snippet has *no* relation to the `ServerGui` instance in which `connect()` was called. – Damien_The_Unbeliever Sep 03 '17 at 07:22
  • So what do you think I can do about it. (Sorry I'm still learning the ropes on C#) –  Sep 03 '17 at 07:28
  • I'm not sure why you are creating a `Menu` but you need to pass the menu a reference to your `ServerGui` form _or_ you should make your stream instances public properties that you can be accessed by your menu. – Deolus Sep 03 '17 at 07:52
  • Setting it to public didn't work. –  Sep 03 '17 at 08:34

1 Answers1

0

If the send method is called before the connect method the the StreamWriter sw is set to null and a NullReferenceException is thrown inside the send method.

A quick fix is to check the sw property before using it like:

public void send(string msg)
{
    if (sw != null)
        sw.WriteLine(msg);
}

or with a newer C# language feature a little bit shorter:

public void send(string msg)
{
    sw?.WriteLine(msg);
}

EDIT:

The problem is that with the line ServerGUI sgui = new ServerGUI(); you create a new (second) ServerGUI form after hiding the former one that hat its own sw property. This sw property has been never initialized because the created StreamWriter instance is part of the first gui that you just have hidden.

Although this design (strong coupling of forms without a data/service layer) is not ideal, a way to fix this is to pass the form instance to the Menu. E.g.

var menu = new Menu(); 
menu.ServerGui = this; 
menu.Show(); 

and of course the Menu class has to introduce a ServerGUI property like public

class Menu { 
   ...
   public ServerGUI ServerGui {get; set;}

   private void button1_Click(object sender, EventArgs e)
   {
        ServerGui.close();
   }

   private void button2_Click(object sender, EventArgs e)
   {
        ServerGui.send(textBox1.Text);
   }
Ralf Bönning
  • 14,515
  • 5
  • 49
  • 67
  • That stopped the error, but it still doesn't send. So this is how my program works: There is a button on the ServerGUI form called button1. When you press it, it connects to the client. Once it has connected, it closes ServerGUI and opens the Menu form. On the menu form, there are two buttons and a textbox. Button1 disconnects from the client (which I never press so can't be the problem, I also tried removing the code but that didn't fix it) and button2 which calls the send method. –  Sep 03 '17 at 09:34
  • @TheTrialBot - I have edited the answer to address the main problem, that you are using two ServerGUI instances. – Ralf Bönning Sep 03 '17 at 09:51
  • Yes, this worked! Thank you. I have been trying to get it to work for a while now. –  Sep 03 '17 at 10:35