-2

I'm trying to make a client and server which can read and write info back and forth between each other. I can write from the client and server reads it but not vise versa and I have no idea why. Nobody on here seems to know when I asked before and I cant find anything online that works. If you know please tell me and not tell me to go read an article about TCP because it doesn't help at all.

Client:

namespace ExampleClient
{
public partial class Form1 : Form
{
public static bool IsConnected;
public static NetworkStream Writer;
public static NetworkStream Receiver;

public Form1()
{
    InitializeComponent();
}

private void BtnConnect_Click(object sender, EventArgs e)
{
    TcpClient Connector = new TcpClient();
    Connector.Connect(TxtIP.Text, Convert.ToInt32(TxtPort.Text));
    IsConnected = true;
    Writer = Connector.GetStream();
    Console.WriteLine("Connected");

    System.Threading.Thread Rec = new System.Threading.Thread(new System.Threading.ThreadStart(Receive));
    Rec.Start();
}

private void BtnWrite_Click(object sender, EventArgs e)
{
    try{
        byte[] Packet = Encoding.ASCII.GetBytes("Client Write Test");
        Writer.Write(Packet, 0, Packet.Length);
        Writer.Flush();}
    catch{
        try { Writer.Close();} catch { }}
}

public static void Receive()
{
    while (true){
        try{
            byte[] RecPacket = new byte[1000];
            Receiver.Read(RecPacket, 0, RecPacket.Length);
            Receiver.Flush();
            string Message = Encoding.ASCII.GetString(RecPacket);
            MessageBox.Show(Message);
        }
        catch { break;}
    }
}
}
}

Receiver/ Server:

namespace ExampleServer
{
public partial class Form1 : Form
{
public static NetworkStream Writer;
public static NetworkStream Receiver;

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    TcpListener Server = new TcpListener(2002);

    Server.Start();
    TcpClient Connection = Server.AcceptTcpClient();
    Receiver = Connection.GetStream();
    System.Threading.Thread Rec = new System.Threading.Thread(new System.Threading.ThreadStart(Receive));
    Rec.Start();
}

public static void Receive()
{
    while (true)
    {
        try
        {
            byte[] RecPacket = new byte[1000];
            Receiver.Read(RecPacket, 0, RecPacket.Length);
            Receiver.Flush();
            string Message = Encoding.ASCII.GetString(RecPacket);
            MessageBox.Show(Message);

            try{
                byte[] Packet = Encoding.ASCII.GetBytes("Server Write Test");
                Writer.Write(Packet, 0, Packet.Length);
                Writer.Flush();}
            catch{
                try { Writer.Close(); } catch { }}
        }
        catch { break; }
    }
}
}
}

So when the server reads the message from the client, it displays it which works fine but when it goes to write a message back to the client, it crashes with the error "system.nullreferenceeexception: object reference not set to an instance of an object. at exampleserver.form1.receive()".

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
Rachel Dockter
  • 946
  • 1
  • 8
  • 21
  • 2
    Possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Jason Watkins Mar 31 '16 at 21:51
  • Where exactly are you getting the NullReferenceException? – Jason Watkins Mar 31 '16 at 21:52
  • no i know what a null reference is, im not sure why its giving me that error here and telling me to learn how to fix a null reference wont help me at all. i need help specificly for my example – Rachel Dockter Mar 31 '16 at 21:53
  • im getting that error on the server application when it goes to send the message between "byte[] packet.... and writer.flush()" – Rachel Dockter Mar 31 '16 at 21:53
  • Let me be more specific. What object(s) are null when when the exception is triggered? – Jason Watkins Mar 31 '16 at 21:55
  • all it says is the error is "at exampleserver.form1.receive()" i cant see why any object would be null – Rachel Dockter Mar 31 '16 at 21:56
  • 2
    That's what the debugger is for. I suggest you read the linked question's top answer thoroughly and apply the information in it. If you can't tell me exactly what objects are null, you haven't fully applied the information in the post – Jason Watkins Mar 31 '16 at 21:59
  • ok give me a minuite ill find out exacly what line is giving me the error – Rachel Dockter Mar 31 '16 at 22:00
  • "Writer.Write(Packet, 0, Packet.Length);" is the exacly line where it crashes and gives me the error – Rachel Dockter Mar 31 '16 at 22:14
  • Make Connection global : public static TCPClient Connection. Then write to Connection. – jdweng Mar 31 '16 at 22:14
  • @Rachel So, now you know that the problem is either with `Writer` or `Packet`. `Packet` is initialized in the preceding line, so it's easy to rule that out. So now you need to figure out why `Writer` is null... – Jason Watkins Mar 31 '16 at 22:16
  • its the writer, hold on let me try and do what jdweng said – Rachel Dockter Mar 31 '16 at 22:17
  • i made it public and fixed the writer i think, its not crashing anymore but the client isnt showing the message box from the server, im trying to see if its a server problem or client problem – Rachel Dockter Mar 31 '16 at 22:25
  • its still not sending and it doesnt crash, i have no idea whats wrong ffs – Rachel Dockter Mar 31 '16 at 22:35

3 Answers3

1

The problem why your client never receives the response is due to that you never let it.

You never initialize the client's Receiver stream, the application isn't breaking because A) the error is thrown in a different thread, B) you just break the while loop when the error occurs, you really need to log the error somehow.

Use only one NetworkStream. The stream supports simultaneous receiving and sending, and it's much easier having one than two - you will not forget to initialize it as easily.

In the future you should also look into handling your messages. As TCP is stream based, you can get messages in any possible way; one third of a message, half a message, or just one byte at a time (etc.). There are a few ways to solve this, but the best method is length-prefixing (or length prefixing).

Length-prefixing combined with header-prefixing makes your messages as reliable as they get when it comes to receiving them properly. If done correctly you can always be sure that you get a message containing the correct, and correct amount of data.

Length- and header-prefixing means that you prefix each message with it's correct length, and a header telling what the message is for. This is how it's composed:

  1. Read the length of the message (the amount of bytes)
  2. Store the length in an Integer.
  3. Choose a header (usually a one-byte header is enough).
  4. Concatenate the length with the header, and then that with the rest of the message.

This will produce the following structure:

[Length (4 bytes)][Header (1 byte)][Message (?? byte(s))]

To read it:

  1. Read the first 4 bytes, and convert the returned array to an Integer.
  2. Read the next byte to get the header.
  3. Read until you've read the whole length of the message. Determine what you'll do with the message based on the header.

Reading that sequence you will always know how much to read and expect from the other endpoint, and thus you won't have a problem with partial or messages being lumped together.

Hope this helps!

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
0

Only one usage of each socket address (protocol/network address/port) is normally permitted... don't start TcpListener.

jkdev
  • 11,360
  • 15
  • 54
  • 77
  • Welcome to StackOverflow. Your post has been flagged as possible spam. To avoid deletion, please consider editing your answer with more details to help solve OP's question. Thank you! – Bryce Siedschlaw Nov 22 '18 at 21:24
-1

I don't think you are initializing Writer. Make sure that gets initialized before calling it.

You catch the first NullReferenceException, but then in the catch, you call Writer again, throwing a new one.

Jestin
  • 330
  • 2
  • 13
  • 1
    `Writer` and `Receiver` are both of the same type (`NetworkStream`). That means that they both have all of the same methods. In fact, you don't need them to be separate objects at all. You can use a single stream to both read and write – Jason Watkins Mar 31 '16 at 22:19
  • Both `Receiver` and `Writer` are network streams. Both can be read from and written to. I assumed that your server was reading from one endpoint and relaying to another. It sounds like you simply want to respond on the existing stream. I don't think you need `Writer` at all. Just call `'Write()` on your `Receiver` object. – Jestin Mar 31 '16 at 22:21
  • thanks, im horrible at networking so i dont really understand that much of what you said. its not crashing anymore and looks like its sending it but im not getting the message box showing at the client again – Rachel Dockter Mar 31 '16 at 22:24