我用c#写了一个客户端和服务器程序。出现丢包概率大的问题
最近接到个项目 写个响应服务器程序,要求最大连接要有1000个。为了方便测试,我用数组写了socket并用异步发送数据的客户端。能生成100个连接。连接都接上了,发送也都发送出去了。但是在服务器端出现了接收时候丢包的现象。不知道各位高手有什么好点的解决方法。麻烦了 注意:这个响应服务器程序还有个功能是把接收到的数据转发给另外一个服务器,在测试的时候要用socket tool建立个服务器接收数据或者把转发的代码注释掉下面是服务器端代码
namespace TCPServer
{
public partial class Form1 : Form
{
private Socket s = null;
private Socket d = null;
private List<Socket> m_list = null;
private delegate void setlist(string s1, string s2);
private delegate void setTextbox(string s);
private delegate void removelist(Socket s);
private setlist SetListview;
private setTextbox setbox;
private removelist remove;
private byte[] date = new byte[1024];
private static byte[] RevDate = new byte[1024];
public Form1()
{
InitializeComponent();
}
private void setListView(string s1, string s2)
{
lvUser.Items.Add(new ListViewItem(new string[] { s1, s2 }));
}
private void setboxcontext(string s)
{
tbRevMsg.Text = s + Environment.NewLine+tbRevMsg.Text;
}
private void removeitem(Socket st)
{
foreach (ListViewItem item in lvUser.Items)
{
if (st.RemoteEndPoint.ToString()==(item.SubItems[0].Text.ToString()+":"+item.SubItems[1].Text.ToString()))
{
lvUser.Items.Remove(item);
break;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_list = new List<Socket>();
SetListview = new setlist(setListView);
setbox = new setTextbox(setboxcontext);
remove = new removelist(removeitem);
}
private void btStart_Click(object sender, EventArgs e)
{
//tsmiSetting.Enabled = false;
d = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int port1 = 6000;
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint iep1 = new IPEndPoint(ip, port1);
d.Connect(iep1);
btStart.Enabled = false;
this.tbPort.Enabled = false;
//if (tsmiAuto.Checked)
//{
// btSend.Enabled = false;
//}
int port;
if(!(int.TryParse(this.tbPort.Text.ToString().Trim(), out port)))
{
port = 8000;
}
try
{
IPEndPoint iep = new IPEndPoint(IPAddress.Any, port);
s.Bind(iep);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
MessageBox.Show("端口占用!");
return;
}
s.Listen(5);
s.BeginAccept(new AsyncCallback(Accept), s);
}
private void Accept(IAsyncResult iar)
{
Socket socket = (Socket)iar.AsyncState;
Socket NewSocket = socket.EndAccept(iar);
System.Diagnostics.Debug.WriteLine(NewSocket.RemoteEndPoint.ToString() +" "+ DateTime.Now.ToString());
this.Invoke(SetListview, new object[] { ((IPEndPoint)NewSocket.RemoteEndPoint).Address.ToString(), ((IPEndPoint)NewSocket.RemoteEndPoint).Port.ToString() });
m_list.Add(NewSocket);
socket.BeginAccept(new AsyncCallback(Accept), socket);
//if (tsmiAuto.Checked)
//{
try
{
NewSocket.BeginReceive(RevDate, 0, 1024, SocketFlags.None, new AsyncCallback(Receive), NewSocket);
//date = Encoding.Default.GetBytes("Hello World!");
//NewSocket.BeginSend(date, 0, date.Length, SocketFlags.None, new AsyncCallback(Send), NewSocket);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
m_list.Remove(NewSocket);
this.Invoke(remove, new object[] { NewSocket });
}
//}
//else
//{
// try
// {
// NewSocket.BeginReceive(RevDate, 0, 1024, SocketFlags.None, new AsyncCallback(HandReceive), NewSocket);
// }
// catch (Exception ex)
// {
// System.Diagnostics.Debug.WriteLine(ex.Message);
// m_list.Remove(NewSocket);
// this.Invoke(remove, new object[] { NewSocket });
// }
//}
}
private void Send(IAsyncResult iar)
{
Socket OtherSocket = (Socket)iar.AsyncState;
int Len = OtherSocket.EndSend(iar);
if (Len == date.Length)
{
this.Invoke(setbox, new object[] { "服务器发送:"+Encoding.Default.GetString(date)});
}
else
{
this.Invoke(setbox, new object[] { Encoding.Default.GetString(date) + "发送失败!" });
}
}
private void Receive(IAsyncResult iar)
{
Socket OtherSocket = (Socket)iar.AsyncState;
Socket newsocket = d;
try
{
int Len = OtherSocket.EndSend(iar);
if (Len == 0)
{
m_list.Remove(OtherSocket);
this.Invoke(remove, new object[] { OtherSocket });
return;
}
this.Invoke(setbox, new object[] { "服务器收到(" + OtherSocket.RemoteEndPoint.ToString() + "):" + Encoding.Default.GetString(RevDate, 0, Len) });
date = new byte[Len];
Buffer.BlockCopy(RevDate, 0, date, 0, Len);
newsocket.BeginSend(RevDate, 0, date.Length, SocketFlags.None, new AsyncCallback(Send), newsocket);
//RevDate = new byte[1024];
Array.Clear(RevDate,0,Len);
OtherSocket.BeginReceive(RevDate, 0, 1024,SocketFlags.None, new AsyncCallback(Receive), OtherSocket);
}
catch (Exception ex)
{
m_list.Remove(OtherSocket);
this.Invoke(remove, new object[] { OtherSocket });
}
}
private void HandReceive(IAsyncResult iar)
{
Socket ClientSocket = (Socket)iar.AsyncState;
int len;
try
{
len = ClientSocket.EndReceive(iar);
if (len == 0)
{
m_list.Remove(ClientSocket);
this.Invoke(remove, new object[] { ClientSocket });
return;
}
this.Invoke(setbox, new object[] { "服务器收到(" + ClientSocket.RemoteEndPoint.ToString() + "):" + Encoding.Default.GetString(RevDate, 0, len) });
//RevDate = new byte[1024];
Array.Clear(RevDate, 0, len);
ClientSocket.BeginReceive(RevDate, 0, 1024, SocketFlags.None, new AsyncCallback(HandReceive), ClientSocket);
}
catch (Exception ex)
{
m_list.Remove(ClientSocket);
this.Invoke(remove, new object[] { ClientSocket });
}
}
private void btSend_Click(object sender, EventArgs e)
{
if (lvUser.FocusedItem != null)
{
foreach (Socket s in m_list)
{
if (s.RemoteEndPoint.ToString() == (lvUser.SelectedItems[0].SubItems[0].Text.ToString() + ":" + lvUser.SelectedItems[0].SubItems[1].Text.ToString()))
{
date = Encoding.ASCII.GetBytes(tbMessage.Text.ToString().Trim());
s.BeginSend(date, 0, date.Length, SocketFlags.None, new AsyncCallback(Send), s);
}
}
}
else
{
MessageBox.Show("没有选择用户!");
}
}
}
}
--------------------编程问答-------------------- 接下来是测试用的客户端代码
--------------------编程问答-------------------- 麻烦大家了 --------------------编程问答-------------------- 看晕了,对通讯机制不怎么精通,不过还是顶一个 --------------------编程问答-------------------- 太长了,看得眼花缭乱。 --------------------编程问答-------------------- 。。。。希望大家多多给意见啊 --------------------编程问答-------------------- TCP/IP 通讯是不会出现丢包现象的,传输过程中如果丢包,它会自动重新发一次,这些底层的操作时不需要我们关心的。但是它会出现分包、黏包现象,这是没法避免的。我们通常的解决办法,就是设计自己的包协议:包头+包体长度+包体,每次发送过后,先判断包头标示,然后取出包头,解析包头得到包体长度,通过包体长度取出包体,解析包体。OK!这一系列机制通常会实现成一个环形队列来执行。
namespace WindowsApplication2
{
public partial class Form1 : Form
{
Thread th;
private Socket[] s = new Socket[100];
private delegate void setlist(string s1, string s2);
private setlist SetListview;
private delegate void setTextbox(string s);
private setTextbox setbox;
private byte[] date = new byte[1024];
public Form1()
{
InitializeComponent();
}
private void setListView(string s1, string s2)
{
listView1.Items.Add(new ListViewItem(new string[] { s1, s2 }));
}
private void setboxcontext(string s)
{
listBox1.Items.Add(s);
}
private void button1_Click(object sender, EventArgs e)
{
int port = 8000;
IPAddress ip = IPAddress.Parse("127.0.0.1");
for (int i = 0; i < 100; i++)
{
IPEndPoint iep=new IPEndPoint(ip,port);
s[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
th.Start();
s[i].Connect(iep);
this.Invoke(SetListview, new object[] { ip.ToString(),port.ToString() });
date = Encoding.ASCII.GetBytes("a");
s[i].BeginSend(date, 0, date.Length, SocketFlags.None, new AsyncCallback(check), s[i]);
//port++;
}
}
private void check(IAsyncResult iar)
{
Socket OtherSocket = (Socket)iar.AsyncState;
int Len = OtherSocket.EndSend(iar);
if (Len == date.Length)
{
this.Invoke(setbox, new object[] { "服务器发送:" + Encoding.Default.GetString(date) });
}
else
{
this.Invoke(setbox, new object[] { Encoding.Default.GetString(date) + "发送失败!" });
}
}
private void Form1_Load(object sender, EventArgs e)
{
setbox = new setTextbox(setboxcontext);
SetListview = new setlist(setListView);
}
//private void connect()
//{
//}
}
}
补充:.NET技术 , C#