TCP读取和客户端和服务器写 [英] TCP read and write from client and server

查看:145
本文介绍了TCP读取和客户端和服务器写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图做一个客户端和服务器,可以读取和写入信息来回彼此之间。我可以从客户端写入和服务器读取它,但不能反之亦然,我不知道为什么。在这里似乎没有人知道什么时候我问过,我不能在网上找到任何工作。如果你知道,请告诉我,不告诉我去了解TCP的文章,因为它不利于在所有

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.

客户:

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;}
    }
}
}
}

接收器/服务器:

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; }
    }
}
}
}



因此,当服务器读取来自客户端的消息,它会显示它工作正常,但是当它写一个消息返回到客户端,它与错误崩溃system.nullreferenceeexception:不设置到对象的实例对象引用。在exampleserver.form1.receive()。

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()".

推荐答案

为什么你的客户端永远不会收到响应这个问题是由于你永远不会让它。

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

您从未初始化客户端的接收流,应用程序不断裂了,因为 A)的错误是在不同的线程抛出, B)您刚才发生错误时打破了,而循环,你真的需要记录错误弄好了。

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.

使用只有一个的NetworkStream 。流支持同时接收和发送,而且它有一个超过两容易得多 - 你不会忘记那样容易初始化

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.

在未来,你也应该考虑处理您的邮件。由于TCP是基于流的,你可以在任何可能的方式的信息;消息的三分之一,一半的消息,或在一个时间(等)只是一个字节。有要解决这几个方法,但是最好的方法是的长度前缀的(或长度前缀的)。

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. 阅读信息(字节数)

  2. 的长度
  3. 存储长度一个整数。

  4. 选择一个头(通常是一个字节的头就足够了)。

  5. 串连长度的头,然后,随着消息的其余部分

  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.

这将产生以下结构:

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

要阅读:


  1. 读取前4个字节,返回数组转换为整数。

  2. 读取下一个字节,以获得头。

  3. 阅读您已经阅读了整个长度,直到消息的。确定你会根据标题信息做什么。

阅读该序列,你将永远知道多少阅读和期望从另一个端点,这样的话你不会有局部或消息混为一谈的问题。

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.

希望这有助于!

这篇关于TCP读取和客户端和服务器写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆