空的缓冲套接字
本文关键字:套接字 缓冲 | 更新日期: 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 个字节(。
您可能会发现这对于进一步理解这一点很有用。