c#异步tcp编程多客户端文件传输,只能一个客户端接收数据

itneste 2011-03-30 03:59:20
一个客户端连接的时候可以正常的传输文件,当开启第二个客户端时先前开启的客户端就不传输数据了。后开的客户端个也不会提示文件传输完毕!【只能为一个客户端服务???】异步的tcp不是多线程的吗?怎么会不能同时处理呢?
服务端发送数据的时候如果不sleep一下,会有10055错误,从网上看到似乎是客户端读的太慢,所有导致此错误。
初学网络编程,忘各位不吝赐教~~谢谢、、


服务器端窗体代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace TcpServer
{
public partial class FrmServer : Form
{
private TcpListener serverSocket;
private NetworkStream ns;
private bool _isExit = false;
//private AsyncCallback Accept;
private delegate void noArgsDelegate();
private ClientObj client;
public FrmServer()
{
InitializeComponent();
//tempList = new List<byte>();
//bData=new byte[8192];
}

private void btnStart_Click(object sender, EventArgs e)
{
this.btnStart.Enabled = false;
try
{
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9000);
serverSocket = new TcpListener(ipep);
serverSocket.Start();
//Accept = new AsyncCallback(OnAccept);
serverSocket.BeginAcceptTcpClient(new AsyncCallback(OnAccept), serverSocket);
}
catch (Exception ex)
{
this.btnStart.Enabled = true;
MessageBox.Show(ex.Message, "Exceptions", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnAccept(IAsyncResult iar)
{
try
{
client = new ClientObj(serverSocket.EndAcceptTcpClient(iar));

noArgsDelegate noArgs = delegate {
this.lstMsg.Items.Add(client.Client.Client.RemoteEndPoint.ToString()+" - Connect:");
};
this.BeginInvoke(noArgs);
if (!_isExit)
{
serverSocket.BeginAcceptTcpClient(new AsyncCallback(OnAccept), serverSocket);
}
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client.Ns);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exceptions", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnRead(IAsyncResult iar)
{
int iCount=0;
NetworkStream ns = (NetworkStream)iar.AsyncState;
client.Ns = ns;
iCount= client.Ns.EndRead(iar);//如果此处收到20个字节
if (iCount > 0)
{
CacheData(client.BData,iCount);
if (!_isExit)
{
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client.Ns);
}
}
}
private void CacheData(byte[] data,int len)
{
client.TempList.AddRange(data);
client.TempList.RemoveRange(len, client.TempList.Count - len);
byte[] tData = client.TempList.ToArray();
client.TempList.Clear();
client.List.AddRange(tData);
while (client.List.Count >= 12)//如果长度大于12了,则分析字符长度
{
Msg msg = new Msg(client.List.ToArray());//获取各个包的长度
int cellLen = msg.IAssistMsgLen + msg.IByteDataLen + 12;//一个数据包的长度
//client.List.RemoveRange(cellLen, client.List.Count - cellLen);
if (client.List.Count >= cellLen)//如果缓存中的数据够一个数据包
{
msg.GetBytes();//到此时就获取了一个数据包中的信息了
ExecuteCommand(msg);
client.List.RemoveRange(0, cellLen);//移除已经存储的部分
}
else
{
break;
}
}
}
private void ExecuteCommand(Msg _msg)
{
switch (_msg.CmdCommand)
{
case Command.Message:
{
noArgsDelegate noArgs = delegate
{
this.lstMsg.Items.Add(Encoding.Unicode.GetString(_msg.ByteData, 0, _msg.IByteDataLen));
this.lstMsg.TopIndex = lstMsg.Items.Count - 1;
};
this.BeginInvoke(noArgs);
}; break;
case Command.Download:
{
//需要从附加信息中获取到 ----|文件名|
string strFileName = Encoding.Unicode.GetString(_msg.ByteAllData, 12, _msg.IAssistMsgLen);
FileStream fs = new FileStream(strFileName, FileMode.Open, FileAccess.Read,FileShare.Read);
BinaryReader br = new BinaryReader(fs);
byte[] bData=new byte[4096-_msg.IAssistMsgLen-_msg.IByteDataLen];
Msg msg = new Msg();
int count=0;
List<byte> list = new List<byte>();
while ((count=br.Read(bData,0,bData.Length))>0)
{

msg.CmdCommand = Command.Upload;
long fileSize = fs.Length;
msg.StrAssistMsg = strFileName+"|"+fileSize;
list.AddRange(bData);
list.RemoveRange(count, list.Count - count);
msg.ByteData = list.ToArray();
byte[] bMsg = msg.ToBytes();
Thread.Sleep(1);
client.Ns.BeginWrite(bMsg, 0, bMsg.Length, new AsyncCallback(OnWrite), client.Ns);
list.Clear();
}
}; break;
default: break;
}
}
private void OnWrite(IAsyncResult iar)
{
NetworkStream ns = (NetworkStream)iar.AsyncState;
client.Ns = ns;
client.Ns.EndWrite(iar);
}
}
}

...全文
545 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
wanggenhu0 2012-04-08
  • 打赏
  • 举报
回复
你好,可以把例子共享一下吗
itneste 2011-03-31
  • 打赏
  • 举报
回复


谢谢wwlyqin

private void OnRead(IAsyncResult iar)
{
int iCount=0;//2
ClientObj client = (ClientObj)iar.AsyncState;//1
NetworkStream ns = client.Ns;
//NetworkStream ns = (NetworkStream)iar.AsyncState;
iCount= client.Ns.EndRead(iar);//如果此处收到20个字节
//iCount = ns.EndRead(iar);
if (iCount > 0)
{
CacheData(client,client.BData,iCount);
if (!_isExit)
{
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new
AsyncCallback(OnRead), client.Ns);//此处client.Ns改为client即可 呵呵
}
}
}

itneste 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wwlyqin 的回复:]

你把作用区域先规范好。
C# code

private void OnAccept(IAsyncResult iar)
{
try
{
TcpListener s= iar.AsynState as TcpListener;
ClientObj clien……
[/Quote]

wwlyqin,改了变量之后遇到一个问题,

private void OnAccept(IAsyncResult iar)
{
try
{
TcpListener listener = (TcpListener)iar.AsyncState;
ClientObj client = new ClientObj(listener.EndAcceptTcpClient(iar));
noArgsDelegate noArgs = delegate
{
this.lstMsg.Items.Add(client.Client.Client.RemoteEndPoint.ToString() + " - Connect:");
};
this.BeginInvoke(noArgs);
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client);
if (!_isExit)
{
listener.BeginAcceptTcpClient(new AsyncCallback(OnAccept), listener);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exceptions", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnRead(IAsyncResult iar)
{
int iCount=0;//2
ClientObj client = (ClientObj)iar.AsyncState;//1
NetworkStream ns = client.Ns;
//NetworkStream ns = (NetworkStream)iar.AsyncState;
iCount= client.Ns.EndRead(iar);//如果此处收到20个字节
//iCount = ns.EndRead(iar);
if (iCount > 0)
{
CacheData(client,client.BData,iCount);
if (!_isExit)
{
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client.Ns);
}
}
}

如果我不加断点,执行到 1 处会提示
Unable to cast object of type 'System.Net.Sockets.NetworkStream' to type 'TcpServer.ClientObj'.
,类型不匹配?我传入的是clientobj类型的啊。
如果在 2 处加一个断点,然后再执行,一切正常(仅测试的但客户端,多的没有测试),
此处(ClientObj)iar.AsyncState;如果使用 as 转换则client为null

家断点才行,这是怎么回事??
itneste 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wwlyqin 的回复:]

你把作用区域先规范好。
C# code

private void OnAccept(IAsyncResult iar)
{
try
{
TcpListener s= iar.AsynState as TcpListener;
ClientObj clien……
[/Quote]

呵呵 晚上不上网 我立刻手术 稍等~~~
hinada99 2011-03-30
  • 打赏
  • 举报
回复
itnest~~~
我们都在研究同一类问题额~~~

YY是大神~~~跟着大神走~~~
WillWang 2011-03-30
  • 打赏
  • 举报
回复
你把作用区域先规范好。

private void OnAccept(IAsyncResult iar)
{
try
{
TcpListener s= iar.AsynState as TcpListener;
ClientObj client = new ClientObj(s.EndAcceptTcpClient(iar));

noArgsDelegate noArgs = delegate {
this.lstMsg.Items.Add(client.Client.Client.RemoteEndPoint.ToString()+" - Connect:");
};
this.BeginInvoke(noArgs);

client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client);
if (!_isExit)
{
s.BeginAcceptTcpClient(new AsyncCallback(OnAccept), s);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exceptions", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

private void OnRead(IAsyncResult iar)
{
ClientObj client = iar.AsyncState as ClientObj;
int iCount=0;
NetworkStream ns = client.ns;

iCount= ns.EndRead(iar);//如果此处收到20个字节
if (iCount > 0)
{
CacheData(client.BData,iCount);
ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client);
}
}
}



程序就是由于变量问题引起的
itneste 2011-03-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 fengyarongaa 的回复:]

如果你调试的话 会发现

你的 步骤在 第一次之后就 完事儿了

没有进入到监听的 回调

还是做异步的 监听回调吧
[/Quote]

不好意思 没太看明白,忘指教~~
ycproc 2011-03-30
  • 打赏
  • 举报
回复
如果你调试的话 会发现

你的 步骤在 第一次之后就 完事儿了

没有进入到监听的 回调

还是做异步的 监听回调吧
itneste 2011-03-30
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 wwlyqin 的回复:]

还有个问题,处理方法里要用局部变量~~否则变量会被更改。
[/Quote]

恩 的确 呵呵 我很多都没有用局部的
itneste 2011-03-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wwlyqin 的回复:]
C# code
private void OnAccept(IAsyncResult iar)
{
try
{
client = new ClientObj(serverSocket.EndAcceptTcpClient(iar));

noArgsDelegate n……
[/Quote]


if (!_isExit)
{
serverSocket.BeginAcceptTcpClient(new AsyncCallback(OnAccept), serverSocket);
}
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client.Ns);



可是这里我在判断如果不退出之后继续接受了。
谢谢ls
WillWang 2011-03-30
  • 打赏
  • 举报
回复
还有个问题,处理方法里要用局部变量~~否则变量会被更改。
WillWang 2011-03-30
  • 打赏
  • 举报
回复

private void OnAccept(IAsyncResult iar)
{
try
{
client = new ClientObj(serverSocket.EndAcceptTcpClient(iar));

noArgsDelegate noArgs = delegate {
this.lstMsg.Items.Add(client.Client.Client.RemoteEndPoint.ToString()+" - Connect:");
};
this.BeginInvoke(noArgs);
if (!_isExit)
{
serverSocket.BeginAcceptTcpClient(new AsyncCallback(OnAccept), serverSocket);
}
client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client.Ns);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exceptions", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}


在 client.Ns.BeginRead(client.BData, 0, client.BData.Length, new AsyncCallback(OnRead), client.Ns);后增加serverSocket.BeginAcceptTcpClient(new AsyncCallback(OnAccept), serverSocket);
让它开始接收下一个链接。

相当于while(socket.Accept()....)
否则接收到一次处理完后就不再主动接受连接了
多看看异步编程吧
itneste 2011-03-30
  • 打赏
  • 举报
回复
itneste 2011-03-30
  • 打赏
  • 举报
回复

客户端窗体代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Diagnostics; //名称空间
using System.Runtime.InteropServices;
namespace Client
{
public partial class FrmClient : Form
{
//[DllImport("kernel32.dll")]
//public static extern bool AllocConsole();
//[DllImport("kernel32.dll")]
//public static extern bool FreeConsole();
private TcpClient clientSocket;
private NetworkStream ns;
private byte[] bData;
private List<byte> lstTemp,list;
private delegate void noArgsDelegate();
private FileStream fs;
private BinaryWriter bw = null;
private string curFileName = null;
private long fRecive = 0;
private bool isExit = false;
private bool isOpen = false;
//private int ReciveCount = 0;
//private EventWaitHandle wait = new EventWaitHandle(false, EventResetMode.ManualReset);
private Stopwatch sw;
public FrmClient()
{
InitializeComponent();
clientSocket = new TcpClient();
lstTemp = new List<byte>();
list = new List<byte>();
}
private void btnConnect_Click(object sender, EventArgs e)
{
this.btnConnect.Enabled = false;
try
{
sw= new Stopwatch();
sw.Start();
clientSocket.BeginConnect(IPAddress.Parse(txtAddress.Text), 9000, new AsyncCallback(OnConnect), clientSocket);
}
catch (Exception ex)
{
this.btnConnect.Enabled = true;
MessageBox.Show(ex.Message,"Exceptions",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
private void OnConnect(IAsyncResult ar)
{
try
{
this.btnConnect.Enabled = false;
clientSocket.EndConnect(ar);
ns = clientSocket.GetStream();
Msg msg = new Msg();
msg.CmdCommand = Command.Message;
msg.StrAssistMsg = "";
string strMsg = "this is the first msg !";
msg.ByteData = Encoding.Unicode.GetBytes(strMsg);
byte[] bMsg = msg.ToBytes();
ns.BeginWrite(bMsg, 0, bMsg.Length, new AsyncCallback(OnWrite), clientSocket);

msg.CmdCommand = Command.Message;
msg.StrAssistMsg = "message";
strMsg = "这";
msg.ByteData = Encoding.Unicode.GetBytes(strMsg);
bMsg = msg.ToBytes();
ns.BeginWrite(bMsg, 0, bMsg.Length, new AsyncCallback(OnWrite), clientSocket);

msg.CmdCommand = Command.Download;
msg.StrAssistMsg = "1.iso";
strMsg = "是";
msg.ByteData = Encoding.Unicode.GetBytes(strMsg);
bMsg = msg.ToBytes();
ns.BeginWrite(bMsg, 0, bMsg.Length, new AsyncCallback(OnWrite), clientSocket);

bData=new byte[8192];
ns.BeginRead(bData, 0, bData.Length, new AsyncCallback(OnRead), ns);
}
catch (Exception ex)
{
noArgsDelegate noArgs = delegate {
this.btnConnect.Enabled = true;
};
this.BeginInvoke(noArgs);
MessageBox.Show(ex.Message, "Exceptions", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnWrite(IAsyncResult ar)
{
ns.EndWrite(ar);
}
private void OnRead(IAsyncResult iar)
{
//NetworkStream nss = (NetworkStream)iar.AsyncState;
int iCount=0;
iCount = ns.EndRead(iar);
if (iCount > 0)
{

CacheData(bData, iCount);
//wait.WaitOne();////////////////////////////////////////
if (!isExit)
{
ns.BeginRead(bData, 0, bData.Length, new AsyncCallback(OnRead), ns);
}
}
}
private void FrmClient_FormClosing(object sender, FormClosingEventArgs e)
{
clientSocket.Close();
}
private void CacheData(byte[] data, int len)
{
lstTemp.AddRange(data);
lstTemp.RemoveRange(len, lstTemp.Count - len);
byte[] tData = lstTemp.ToArray();
lstTemp.Clear();
list.AddRange(tData);
while (list.Count >= 12)//如果长度大于12了,则分析字符长度
{
Msg msg = new Msg(list.ToArray());//获取各个包的长度
int cellLen = msg.IAssistMsgLen + msg.IByteDataLen + 12;//一个数据包的长度
//client.List.RemoveRange(cellLen, client.List.Count - cellLen);
if (list.Count >= cellLen)//如果缓存中的数据够一个数据包
{
msg.GetBytes();//到此时就获取了一个数据包中的信息了
ExecuteCommand(msg);
list.RemoveRange(0, cellLen);//移除已经存储的部分
}
else
{
break;
}
}
//wait.Set();
}
private void ExecuteCommand(Msg _msg)
{
switch (_msg.CmdCommand)
{
case Command.Message:
{
noArgsDelegate noArgs = delegate
{
//this.lstMsg.Items.Add(Encoding.Unicode.GetString(_msg.ByteData, 0, _msg.IByteDataLen));
//this.lstMsg.TopIndex = lstMsg.Items.Count - 1;
};
this.BeginInvoke(noArgs);
}; break;
case Command.Download:
{
//需要从附加信息中获取到 ----|文件名|
string strFileName = Encoding.Unicode.GetString(_msg.ByteAllData, 12, _msg.IAssistMsgLen);
FileStream fs = new FileStream(strFileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] bData = new byte[8180];
Msg msg = new Msg();
int count = 0;
List<byte> list = new List<byte>();
while ((count = br.Read(bData, 0, bData.Length)) > 0)
{

msg.CmdCommand = Command.Upload;
float fileSize = fs.Length;
msg.StrAssistMsg = "1.iso|" + fileSize;
list.AddRange(bData);
list.RemoveRange(count, list.Count - count);
msg.ByteData = list.ToArray();
byte[] bMsg = msg.ToBytes();
ns.BeginWrite(bMsg, 0, bMsg.Length, new AsyncCallback(OnWrite), ns);
}
}; break;
case Command.Upload:
{
string[] strAssist = _msg.StrAssistMsg.Split('|');//文件名|大小
string fileName = strAssist[0];
long fileSize = long.Parse(strAssist[1]);
int cellSize = _msg.IByteDataLen;
if (curFileName == null)
{
curFileName = fileName;
}

if (!isOpen)
{
fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
bw = new BinaryWriter(fs);
isOpen = true;
}
if (fRecive < fileSize && curFileName == fileName)
{
bw.Write(_msg.ByteData, 0, cellSize);
fRecive += cellSize;
if (fRecive == fileSize)
{
fs.Close();
bw.Close();
isOpen = false;
sw.Stop();
MessageBox.Show("Download Success !" +"用时"+sw.ElapsedMilliseconds.ToString());
}
}
}; break;
default: break;
}
}

}
}


客户端Msg类代码:

//和服务器端Msg类一样
itneste 2011-03-30
  • 打赏
  • 举报
回复
服务器端Msg类代码

using System;
using System.Collections.Generic;
using System.Text;

namespace TcpServer
{
enum Command
{
Download,
Upload,
Message,
Null
}

public class Msg
{
private Command cmdCommand;
private string strAssistMsg;//附加消息
private byte[] byteData, byteAllData;
private int iAssistMsgLen;
private int iByteDataLen;

public byte[] ByteAllData
{
get { return byteAllData; }
set { byteAllData = value; }
}

public int IAssistMsgLen
{
get { return iAssistMsgLen; }
set { iAssistMsgLen = value; }
}
public int IByteDataLen
{
get { return iByteDataLen; }
set { iByteDataLen = value; }
}

public string StrAssistMsg
{
get { return strAssistMsg; }
set { strAssistMsg = value; }
}
public byte[] ByteData
{
get { return byteData; }
set { byteData = value; }
}
internal Command CmdCommand
{
get { return cmdCommand; }
set { cmdCommand = value; }
}

public Msg()
{
this.strAssistMsg = null;
this.byteData = null;
this.byteAllData = null;
this.cmdCommand = Command.Null;
}
public Msg(byte[] bMsg)
{
this.byteAllData = bMsg;
this.cmdCommand = (Command)BitConverter.ToInt32(bMsg, 0);//第一个四位:命令
iAssistMsgLen = BitConverter.ToInt32(bMsg, 4);//第二个四位:附加信息长度
iByteDataLen = BitConverter.ToInt32(bMsg, 8);//第三个四位:数据长度
}
public void GetBytes()
{
if (iAssistMsgLen > 0)
{
this.strAssistMsg = Encoding.Unicode.GetString(this.byteAllData, 12, iAssistMsgLen);//第四个四位:附加信息
}
else
{
this.strAssistMsg = null;
}
if (iByteDataLen > 0)
{
this.byteData = new byte[iByteDataLen];
Array.Copy(this.byteAllData,this.iAssistMsgLen+12,this.byteData,0,iByteDataLen);//第五个四位:数据
//this.byteData = Encoding.UTF8.GetString(bMsg, assistMsgLen + dataLen, dataLen);
}
else
{
this.byteData = null;
}
}
public Byte[] ToBytes()
{
List<byte> result = new List<byte>();
//前四位为命令
byte[] bAssistMsg = Encoding.Unicode.GetBytes(strAssistMsg);
result.AddRange(BitConverter.GetBytes((int)cmdCommand));
//再四位为名字长度
if (strAssistMsg != null)
{
result.AddRange(BitConverter.GetBytes(bAssistMsg.Length));
}
else
{
result.AddRange(BitConverter.GetBytes(0));
}
if (byteData != null)
{
result.AddRange(BitConverter.GetBytes(byteData.Length));
}
else
{
result.AddRange(BitConverter.GetBytes(0));
}
if (strAssistMsg != null)
{
result.AddRange(bAssistMsg);
}
if (byteData != null)
{
result.AddRange(byteData);
}
return result.ToArray();
}
}
}


服务器端ClientObj类代码


using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace TcpServer
{
public class ClientObj
{
private TcpClient client;

public TcpClient Client
{
get { return client; }
set { client = value; }
}
private List<byte> list;

public List<byte> List
{
get { return list; }
set { list = value; }
}
private NetworkStream ns;

public NetworkStream Ns
{
get { return ns; }
set { ns = value; }
}
private FileStream fs;
private BinaryReader br;
private BinaryWriter bw;
private byte[] bData;

public byte[] BData
{
get { return bData; }
set { bData = value; }
}
private List<byte> tempList;

public List<byte> TempList
{
get { return tempList; }
set { tempList = value; }
}
public ClientObj(TcpClient _client)
{
client = _client;
bData=new byte[8192];
list = new List<byte>();
tempList = new List<byte>();
ns = client.GetStream();

}
}
}





110,588

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧