当前位置:编程学习 > C#/ASP.NET >>

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   --------------------编程问答-------------------- 谢谢楼上的几位,小弟看过还是不大明白,能说的更清楚些吗?非常棘手现在。 --------------------编程问答--------------------
引用 25 楼 FantasyFreed 的回复:
异步干嘛还用线程,用AsyncCallback启动Receive() 
clientsocket.BeginConnect(remoteEP, new AsyncCallback(Receive), clientsocket); 

照着这个改过来了,可问题还是没有解决,哪位高人再指点指点? --------------------编程问答-------------------- 学习!帮顶 --------------------编程问答--------------------         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#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,