空的缓冲套接字

本文关键字:套接字 缓冲 | 更新日期: 2023-09-27 18:33:32

我有这段代码服务器部分:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using System.Diagnostics;
namespace server
{
    public partial class server : Form
    {
        public  byte[] data;
        public  byte[] data1;
        public static Socket sock ;
        public static List<Socket> sock_li = new List<Socket>();
        public delegate void operation(string s);
        public delegate void operation2();
        public delegate bool verifier();
        public static int nombre = 0;
        public server()
        {
            InitializeComponent();
          this.Show();
          data1 = new byte[1024];
          data = new byte[1024];
          comboBox1.Items.Add(0);
         sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
              IPAddress adress = IPAddress.Parse("127.0.0.1");
              IPEndPoint iep = new IPEndPoint(adress, 4000);
              EndPoint ep = (EndPoint)iep;
              sock.Bind(iep);
              sock.Listen(1000);
               sock_li.Add(sock.Accept());
               if (this.InvokeRequired) Invoke((operation)effectuer4, "le client " + 0 + " a rejoint le chat");
               else effectuer4("le client " + 0 + " a rejoint le chat");
               Thread li = new Thread(liste);
               li.Start();
               Thread ko = new Thread(new ParameterizedThreadStart(listenning));
               ko.Start(0);
          }
        public void liste() {
            nombre = 1;
        while (true)
              {
                  sock_li.Add(sock.Accept());
                  if (this.InvokeRequired) Invoke((operation)effectuer4, "le client " + nombre.ToString() + " a rejoint le chat");
                  else effectuer4("le client " + nombre.ToString() + " a rejoint le chat");
                  if (this.InvokeRequired) Invoke((operation)effectuer5,  nombre.ToString() );
                  else effectuer5( nombre.ToString() );
                  Thread ko = new Thread(new ParameterizedThreadStart(listenning));
                  ko.Start(nombre);
                  nombre++;
              }


        }
        private void effectuer5(string p)
        {
            comboBox1.Items.Add(p);
        }
        public void listenning(Object j)
        {
            int i = (int)j;
            String s="";
            while (true)
            {
                if (sock_li[i].Receive(data) > 0)
                {
                 s = ASCIIEncoding.ASCII.GetString(data);
                              if (this.InvokeRequired) Invoke((operation)effectuer4, "client " + i.ToString() + " : " + s);
                              else effectuer4("client " + i.ToString() + " : " + s);

                }
            }
        }
        private void effectuer(String s)
        {
            textBox1.Text += "serveur:  " + s + "'r'n";
              message.Text  = "";
        }
        private void effectuer4(String s)
        {
            textBox1.Text +=  s + "'r'n"; message.Text = "";
        }
      private void buttonDisconnect_Click(object sender, EventArgs e)
        {
            sock.Close();
            Application.Exit();
             }
    private void buttonSend_Click(object sender, EventArgs e)
        {
           String s = message.Text ;
           data1.Initialize();
            data1 = System.Text.Encoding.ASCII.GetBytes(s);

            int i = int.Parse(comboBox1.SelectedItem.ToString());
            sock_li[i].Send(data1);
       if (InvokeRequired) Invoke((operation)effectuer, s); else effectuer(s);
           }
        }
     }

零件客户端是:

 using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Timers;
    using System.Threading;
    using TrackingUnitSimulator;
    using NHibernate;
    using System.Xml;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Diagnostics;
    using base_donnee;
    namespace GUInterface
    {
        public partial class TrackingUnitClientForm : Form
        {
            #region variables
            public string fich_log = "";
            public Socket sock;
            public IPEndPoint ipEnd = null;
            public static bool connexion = false;
            private static byte[] data;
            public static byte[] data1;
            public  string serial;
            public string[] types= new string[6]{  "EasyTrace"," WatchTrace","MultiTrace","PocketTrace","TrailerTrace","SmartTrace"};
            public static string[] typ = new string[100];
            public static string[] validite = new string[100];
            public static float[] longi = new float[100];
            public static float[] lati = new float[100];
           public static float[] scenarios = new float[100];
            public static int nombre = 0;
           public static TCPClient tcpClient = null;
           public static int[] tab = new int[6];
           public static int debut = 0;
           public static int fin = 0;
           public static string s;
           public int atte = 0;
            public static scenario sc = null;
            #endregion
           #region delegates
           delegate void CommandReceivedCallBack(TCPClient tcpClient, string commandText);
           delegate void faire(string s);
           delegate void faire2(string s1, string s2);
           delegate void masquer(int i);
           delegate void received(string i);
           #endregion

            public void received1(string i)
            {
                receivedCommand.Text += "  New command: " + i + "'r'n";
            }
            #endregion
            public TrackingUnitClientForm(string b, bool ver, string fichier_log, string fichier_scenario)
            {
                InitializeComponent();
                fich_log = fichier_log;
                Disconnexionbt.Hide();
                sc = new scenario(@fichier_scenario);
                serial = b;
                int p = 0;
                Random m = new Random();
                p = m.Next(0, 5);
                if (ver == true)
                {
                    equipment cr = new equipment();
                    cr.enregistrer(b, types[p]);
                }
                label4.Text = types[p];
                label2.Text = serial;
                if (fich_log != "")
                {
                    if (InvokeRequired) Invoke((faire)log, DateTime.Now.ToString() + " | " + "L'équipment num" + serial.ToString() + " se connecte'r'n");
                    else log(DateTime.Now.ToString() + " | " + "L'équipment num" + serial.ToString() + " se connecte'r'n");
                }
                connecter();

                  Thread th = new Thread(listening);
                th.Start();

            }
            public void connecter() {
                try
                {
                    IPAddress adress = IPAddress.Parse("127.0.0.1");
                    ipEnd = new IPEndPoint(adress, 4000);
                    sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    sock.Connect(ipEnd);
                    this.Connexionbt.Hide();
                    this.Disconnexionbt.Show();
                    lblConnectionStatus.Text = "Online";
                    lblConnectionStatus.ForeColor = Color.Blue;
                }
                catch (Exception exc)
                {
                    if (InvokeRequired) Invoke((masquer)masquer1, 4);
                    else
                        this.Disconnexionbt.Hide();
                    lblConnectionStatus.Text = "Offline";
                    lblConnectionStatus.ForeColor = Color.Red;
                    MessageBox.Show(exc.Message, Text);
                }
                }
            public void listening() {
                String s = null;
               try
                {
                repeter:
                    data = new byte[1024];
                s = ASCIIEncoding.ASCII.GetString(data);
                    if (sock.Receive(data) > 0 && s!="")
                    {

                        if (String.Compare(s, "$$Y01") == 0)
                        {
                            if (InvokeRequired) Invoke((received)received1, "Actual Postion Request"); else received1("Actual Postion Request");
                        }
                        else if (String.Compare(s, "$$Y03") == 0)
                        {
                            if (InvokeRequired) Invoke((received)received1, "Stop The Vehicle"); else received1("Stop The Vehicle");
                        }
                        else if (String.Compare(s, "$$Y06") == 0)
                        {
                            if (InvokeRequired) Invoke((received)received1, "Cancel The Stop"); else received1("Cancel The Stop");
                        }
                        else
                        {
                            if (InvokeRequired) Invoke((received)received1, s); else receivedCommand.Text += s + "'r'n";
                        }
                    }
                    data = new byte[0];
                    goto repeter;
                }
                catch { }
            }

        }
    }

但是我有这个问题:当我执行超过 2 个客户端时,一些消息将是空的,尤其是第一个(缓冲区数据为空!! 我该如何解决这个问题?

空的缓冲套接字

 data = new byte[1024];
 s = ASCIIEncoding.ASCII.GetString(data);
 if (sock.Receive(data) > 0 && s!="")
 {

k...这会分配一个新的缓冲区(全零(,解码这个全零缓冲区以获得一个字符串(s(,然后实际上要求数据(忽略任何类型的"成帧"(,不费心解码接收到的数据,然后将s(我们知道来自全零(与我们已经知道它没有的预期字符串进行比较。

所以是的,第一个"接收"总是会错过你的开关,仅仅是因为你没有正确解码。然而!您不能假设每个"接收"都会从单个"发送"中获取数据。这里的TCP只是一个流。您将获得"一些数据",可能是:

  • 恰好一条消息,如果你真的很幸运
  • 消息的一部分
  • 27条小消息
  • 一条消息的结尾和整个第二条消息,以及第三条消息的开始(不完整(

这就是为什么您需要使用"成帧"来检测流上的子消息,例如在基于文本的协议中查找换行符,或在二进制协议中使用长度前缀数据。

由于这是 ASCII,您不必担心部分字符,但您仍然需要保留 Receive 的结果,以便您知道在data内部查看多少字节(即,如果您只从套接字获取 27 个字节,您应该只解码 27 个字节(。

您可能会发现这对于进一步理解这一点很有用。