c#下socket通讯问题!急啊!
在ce环境下用socket的udp实现异步通讯,遇到了一个非常大的麻烦,困扰了我好久都没办法解决,情况是在程序接收和发送消息时经常会出现“卡死”的现象,程序无响应。是不是因为只开一个端口接收和发送的原因?代码如下,求哪位高人指点一下,谢谢。十万火急啊!
--------------------编程问答-------------------- 代码贴出来再说 --------------------编程问答-------------------- #region StartReceive()
/// <summary> 启动数据接收线程. </summary>
/// <returns> 返回启动结果. </returns>
public int StartReceive()
{
try
{
//启动监听线程
m_UDPThread = new Thread(new ThreadStart(Receive));
//m_UDPThread.Name = "RecieveThread";
m_UDPThread.Start();
}
catch(Exception ex)
{
this.FireException(ex);
return Constants.UDP_FAIL;
}
return Constants.UDP_OK;
}
#endregion
#region Receive()
/**
* 数据接收线程内运行的代码.
* 负责接收数据并触发相关事件,直到线程或者监听被终止.
**/
private void Receive()
{
while(true)
{
try
{
Byte[] _received = new Byte[Constants.MAX_COMMAND_LEN];
EndPoint _remoteEP = new IPEndPoint(m_LocalEndPoint.Address, m_LocalEndPoint.Port);
int _bytesReceived = m_Socket.ReceiveFrom(_received, ref _remoteEP);
if(_bytesReceived > 0) //如果接收到的字节数大于0
{
/*
string _tmp;
for(int i =0; i<_bytesReceived; i++)
_tmp = GetString( _received[i] );
Log1.Logger.Info("_tmp:"+ _tmp ));
*/
IPEndPoint _remoteIPEP = _remoteEP as IPEndPoint;
string _strReceived = Utilities.BytesToString(_received);
_strReceived = _strReceived.Substring(0, _bytesReceived);
Log1.Logger.Info("_strReceived2:" + _strReceived);
if(OnDataReceived != null)
{
OnDataReceived(this,new ReceivedEventArgs(_remoteIPEP,_strReceived));
}
}
else
Log1.Logger.Info("有0");
}
catch(SocketException se)
{
//由于本组件中使用UDP,是非连接的,因此10061及10054异常可能根本不会发生。
//10061:连接被拒绝,原因是目标主机无应用程序在相应地址上提供服务;
//10054:一个已经建立的连接被远程主机强行关闭。
if ((se.ErrorCode != 10061) && (se.ErrorCode != 10054))
{
//10004:函数调用中断,ReceiveFrom()函数调用被中止。
if (se.ErrorCode != 10004)
{
this.FireException(se);
}
if (m_State != Constants.UDP_STATE_LISTENING)
{
break;
}
}
}
catch (Exception ex)
{
this.FireException(ex);
if (m_State != Constants.UDP_STATE_LISTENING)
{
break;
}
}
}
if((m_State != Constants.UDP_STATE_IDLE) && (m_State != Constants.UDP_STATE_CLOSING))
{
StopListen();
}
m_State = Constants.UDP_STATE_IDLE;
}
#endregion
#region Send(string _IP,int _Port,string _Data)
/// <summary> 向指定的客户端发送指定消息. </summary>
/// <param name="_Data"> 指定要发送的消息. </param>
/// <param name="_IP"> 指定的目标IP地址. </param>
/// <param name="_Port"> 指定目标地址所绑定的端口号. </param>
/// <returns> 返回发送结果. </returns>
public int Send(string _IP,int _Port,string _Data)
{
try
{
IPEndPoint _remoteEP = new IPEndPoint(IPAddress.Parse(_IP), _Port);
return Send(_remoteEP,_Data);
}
catch(Exception ex)
{
this.FireException(ex);
return Constants.UDP_FAIL;
}
}
#endregion
#region Send(IPEndPoint _EP,string _Data)
/// <summary> 向指定的客户端发送指定消息. </summary>
/// <param name="_Data"> 指定要发送的消息. </param>
/// <param name="_EP"> 指定的目标端点. </param>
/// <returns> 返回发送结果. </returns>
public int Send(IPEndPoint _EP,string _Data)
{
if(m_State != Constants.UDP_STATE_LISTENING)
{
return Constants.UDP_FAIL;
}
try
{
byte[] _databytes = Utilities.StringToBytes(_Data);
SocketPacket _sp = new SocketPacket(_EP,_databytes);
m_Socket.BeginSendTo(_databytes,0,_databytes.Length,SocketFlags.None, _EP,new AsyncCallback(SendCallBack),_sp);
}
catch (Exception ex)
{
this.FireException(ex);
return Constants.UDP_FAIL;
}
return Constants.UDP_OK;
}
#endregion
#region Send(UdpObject _uo)
public int Send(UdpObject _uo)
{
try
{
byte[] _databytes = Utilities.StringToBytes(_uo.Msg);
//EndPoint _remoteEP = _uo.RemoteEndPoint;
SocketPacket _sp = new SocketPacket(_uo.RemoteEndPoint,_databytes);
m_Socket.BeginSendTo(_databytes,0,_databytes.Length,SocketFlags.None, _uo.RemoteEndPoint,new AsyncCallback(SendCallBack),_sp);
}
catch (Exception ex)
{
this.FireException(ex);
return Constants.UDP_FAIL;
}
return Constants.UDP_OK;
}
#endregion
#region SendCallBack(IAsyncResult _ar)
/**
* 发送消息的回调函数.
**/
private void SendCallBack(IAsyncResult _ar)
{
try
{
if(m_Socket != null)
{
int _SentLength = m_Socket.EndSendTo(_ar);
SocketPacket _sp = _ar.AsyncState as SocketPacket;
//如果实际发送的字节数与欲发送的字节数相等,代表数据已完整发送。
if(_sp.DataSend.Length == _SentLength)
{
if(OnSend != null)
{
OnSend(this,new SendEventArgs(_sp.RemoteEndPoint,Utilities.BytesToString(_sp.DataSend)));
}
}
}
}
catch(Exception ex)
{
this.FireException(ex);
}
}
#endregion --------------------编程问答-------------------- 求解 --------------------编程问答-------------------- 在线等,很急啊 --------------------编程问答-------------------- 怎么没有高人指点一下? --------------------编程问答-------------------- mark --------------------编程问答-------------------- mark --------------------编程问答-------------------- 不是吧?还没人??? --------------------编程问答-------------------- 不是吧?一天了都没一点消息,只好自己 --------------------编程问答-------------------- 最大不回答的原因可能是太长,看得累. --------------------编程问答-------------------- 我顶 --------------------编程问答-------------------- 你要把自动生成代码的框架也贴出来啊 这样考到vs2005里比较好调试 --------------------编程问答-------------------- 在接收的那里
Sleep 一下就行了。 --------------------编程问答-------------------- 在
private void Receive()
{
while(true)
{
Thread.Sleep(200);
}
}
--------------------编程问答-------------------- 终于有人回答了,谢谢,我试试看
--------------------编程问答-------------------- 能不能解释一下为什么要 “Thread.Sleep(200);” ??? --------------------编程问答-------------------- 不sleep一下,容易造成拥挤 --------------------编程问答-------------------- 线程死锁?? --------------------编程问答-------------------- 加了sleep,同样出现卡死现象。问题未解决。还是要谢谢上面的兄弟。
本人也怀疑是线程死锁的问题,但不知道怎么调试。 --------------------编程问答-------------------- 发现自己的问题和此处类似,来个连接给大家参考,希望能找出问题来。
http://topic.csdn.net/u/20071212/08/db2663c7-08ba-4553-9fca-b481a10d9328.html --------------------编程问答-------------------- 还有哪位高人指点一下吧/ --------------------编程问答-------------------- 你最好在receive()方法中用socket.BeginReceive()方法和receivecallBack(){socket.Endreceive()}才能实现异步通讯,再创建一个类来存储接收到的内容。 --------------------编程问答-------------------- 这样做从理论上讲可以实现,但在实际应用中会有问题问题出现在,当无客户端接入时While(true){}相当于死循环。当侦听到一个联入时,紧接着又来一个联入时同步就回出现给你有卡的感觉。
我个人偏向是:
1、即时通讯的访问是频繁的就用异步模式。
2、综合考虑你的项目采用什么。
以下是我的一段离子,希望对你有帮助。
public virtual void Start()
{
///判断服务有无启动
if (_isrun)
{
}
_sessionTable = new Hashtable(101);
_recievDataBuffer= new byte[_defaultbuffer];
///初始化Socket
_svr_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
///绑定侦听
_svr_socket.Bind(_iep);
_svr_socket.Listen(_quequelen);
///设置通讯异步模式 接收客户端
_svr_socket.BeginAccept(new AsyncCallback(AcceptClientConn), _svr_socket);
_isrun = true;
} --------------------编程问答-------------------- 实际在应用过程中利用了C#.NET中委托事务 --------------------编程问答-------------------- 异步干嘛还用线程,用AsyncCallback启动Receive()
clientsocket.BeginConnect(remoteEP, new AsyncCallback(Receive), clientsocket);
--------------------编程问答-------------------- Mark --------------------编程问答-------------------- 谢谢楼上的几位,小弟看过还是不大明白,能说的更清楚些吗?非常棘手现在。 --------------------编程问答--------------------
照着这个改过来了,可问题还是没有解决,哪位高人再指点指点? --------------------编程问答-------------------- 学习!帮顶 --------------------编程问答-------------------- private void Receive()
{
while(true)
{
try
{
//Byte[] _received = new Byte[Constants.MAX_COMMAND_LEN];
EndPoint _remoteEP = new IPEndPoint(m_LocalEndPoint.Address, m_LocalEndPoint.Port);
allDone.Reset();
StateObject state = new StateObject();
state.workSocket = m_Socket;
m_Socket.BeginReceiveFrom(state.buffer, 0, StateObject.BufferSize,0, ref _remoteEP,
new AsyncCallback(ReceiveCallback), state);
allDone.WaitOne();
}
catch(SocketException se)
{
//由于本组件中使用UDP,是非连接的,因此10061及10054异常可能根本不会发生。
//10061:连接被拒绝,原因是目标主机无应用程序在相应地址上提供服务;
//10054:一个已经建立的连接被远程主机强行关闭。
if ((se.ErrorCode != 10061) && (se.ErrorCode != 10054))
{
//10004:函数调用中断,ReceiveFrom()函数调用被中止。
if (se.ErrorCode != 10004)
{
this.FireException(se);
}
if (m_State != Constants.UDP_STATE_LISTENING)
{
break;
}
}
}
catch (Exception ex)
{
this.FireException(ex);
if (m_State != Constants.UDP_STATE_LISTENING)
{
break;
}
}
}
if((m_State != Constants.UDP_STATE_IDLE) && (m_State != Constants.UDP_STATE_CLOSING))
{
StopListen();
}
m_State = Constants.UDP_STATE_IDLE;
}
#endregion
private void ReceiveCallback( IAsyncResult ar )
{
try
{
StateObject state = (StateObject) ar.AsyncState;
Socket client = state.workSocket;
EndPoint _remoteEP = new IPEndPoint(m_LocalEndPoint.Address, m_LocalEndPoint.Port);
allDone.Set();
int bytesRead = client.EndReceiveFrom(ar,ref _remoteEP);
string _strReceived = Utilities.BytesToString(state.buffer);
IPEndPoint _remoteIPEP = _remoteEP as IPEndPoint;
if(OnDataReceived != null)
{
OnDataReceived(this,new ReceivedEventArgs(_remoteIPEP,_strReceived));
}//收到数据触发事件
}
catch
{
}
}
这段程序是否正确??? --------------------编程问答-------------------- 怎么都没人回复啊??在等高人出现啊 --------------------编程问答-------------------- ????
--------------------编程问答-------------------- 数据包接收与发送过程中出现问题,另外检查下服务器端口与客户端端口是否一致 --------------------编程问答-------------------- 学习中....
端口没有被占用啊?
我今天就遇到这种错误:"通常每个套接字地址(协议/网络地址/端口)只允许使用一次"
补充:.NET技术 , C#