首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

套接字有关问题

2013-02-03 
求助 套接字问题我是学.net的新手,现在遇到了点问题 ,就是套接字的 多个客户端怎样给服务端发送信息 ,服务

求助 套接字问题
我是学.net的新手,现在遇到了点问题 ,就是套接字的 多个客户端怎样给服务端发送信息 ,服务端是循环接收客户端的连接请求的,现在多个客户端连上后 只能一个客户端给服务端发送。高人请帮助 ,谢谢 .net
[解决办法]
服务器socket listen后,accept会生成1个新的连接,每次你都把这个连接给新的对象,就有多个连接,就可以同时接收多个客户端的发送了。
[解决办法]
服务器端的一个代码例子,包括接收客户端以及接收数据


    /// <summary>
    /// 收包处理委托
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="socket"></param>
    /// <returns></returns>
    public delegate bool ReceivePacketHandle(byte[] buffer, Socket socket);

    /// <summary>
    /// 客户端接受委托
    /// </summary>
    public delegate void ClientChangedHandle(object state); 

    public abstract class PacketTransferBase
    {
        /// <summary>
        /// Socket列表
        /// </summary>
        public SortedList<int, Socket> SocketClientList { get; private set; }

        /// <summary>
        /// 客户端接收事件
        /// </summary>
        public event ClientChangedHandle OnClientAccepted;

        /// <summary>
        /// 客户端关闭事件
        /// </summary>
        public event ClientChangedHandle OnClientClosed;

        /// <summary>
        /// 收包处理事件
        /// </summary>
        public event ReceivePacketHandle OnReceivePacket;

        public PacketTransferBase()
        {
            SocketClientList = new SortedList<int, Socket>();           
        }

        /// <summary>
        /// 保存客户端,以待每次接收后进行判断等功能
        /// </summary>
        /// <param name="socketClient"></param>
        protected void AddClient(Socket socketClient)
        {
            lock (SocketClientList)
            {


                HYTLogging.NCLogger.GetInstance().WriteInfoLog(string.Format("Add Socket:{0}.{1}", socketClient.Handle, socketClient.Connected));
                SocketClientList.Add(socketClient.Handle.ToInt32(), socketClient);
            }
            //bufferList.Add(clientCount, new byte[1024]);
            if (OnClientAccepted != null)
            {
                OnClientAccepted(socketClient.Handle.ToInt32());
            }
        }

        /// <summary>
        /// 接收信息
        /// </summary>
        /// <param name="ar"></param>
        protected void ReceiveMessage(IAsyncResult ar)
        {
            try
            {
                StateObject so = (StateObject)ar.AsyncState;
                Socket socket = so.workSocket;
                //var socket = ar.AsyncState as Socket;

                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx
                var length = socket.EndReceive(ar);
                byte[] actualData = new byte[length];
                Array.Copy(so.buffer, 0, actualData, 0, length);
                //fileManager.ReceivePacket(actualData);
                HYTLogging.NCLogger.GetInstance().WriteInfoLog(string.Format("TCPServer.ReceiveMessage: buffer.{0} at Socket.{1} with buffer[23].{2},buffer[24].{3}", length, socket.Handle, so.buffer[23], so.buffer[24]));
                //fileManager.ReceivePacket(actualData, socket);
                //FileTransferManagerServer server = FileTransferManagerServer.GetInstance();
                //server.ReceivePacket(actualData, socket);
                bool continueReceive = false;


                if (OnReceivePacket != null)
                {
                    continueReceive = OnReceivePacket(actualData, socket);
                }

                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)
                //socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
                if (continueReceive)
                {
                    socket.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReceiveMessage), so);
                }
                else
                {
                    Clean(socket);
                    //socket.Close();
                }
            }
            catch (Exception ex)
            {
                HYTLogging.NCLogger.GetInstance().WriteInfoLog(ex.Message + ex.StackTrace);
            }
        }

        /// <summary>
        /// 从列表中移除Socket,并关闭Socket
        /// </summary>
        /// <param name="socket"></param>
        protected void Clean(Socket socket)
        {
            HYTLogging.NCLogger.GetInstance().WriteInfoLog(string.Format("Clean Socket:{0}.{1}", socket.Handle, socket.Connected));
            int socketHandle = socket.Handle.ToInt32();
            lock (SocketClientList)
            {
                if (SocketClientList.ContainsKey(socketHandle))
                {
                    SocketClientList.Remove(socketHandle);


                }
            }
            socket.Close();
            if (OnClientClosed != null)
            {
                OnClientClosed(socketHandle);
            }
        }
    }   

    /// <summary>
    /// TCP服务器端
    /// </summary>
    public class TCPServer : PacketTransferBase
    {
        public string ServerIP { get; set; }
        public int ServerPort { get; set; }
        
        //public Socket[] SocketClientList { get; private set; }
        
        private static TCPServer tcpServer = new TCPServer();
        Socket socketServer = null;
        //FileManager fileManager = new FileManager(FileControl.FileReceive, TCPModel.TCPServer);
        //FileManager fileManager = new FileManager(FileControl.FileSend, TransferModel.TCPServer);

        private TCPServer()
        {
            //SocketClientList = new Socket[10];   
            //SocketClientList = new SortedList<int, Socket>();            
        }

        public static PacketTransferBase GetInstance()
        {
            return tcpServer;
        }

        /// <summary>
        /// 服务器端建立侦听
        /// </summary>
        public void CreatListener()
        {
            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)
            socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //将该socket绑定到主机上面的某个端口
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx
            //socketServer.Bind(new IPEndPoint(IPAddress.Any, 4530));


            socketServer.Bind(new IPEndPoint(IPAddress.Parse(ServerIP), ServerPort));

            //启动监听,并且设置一个最大的队列长度
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx
            socketServer.Listen(100);

            //开始接受客户端连接请求
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx
            socketServer.BeginAccept(new AsyncCallback(ClientAccepted), socketServer);
        }
        
        /// <summary>
        /// 接收客户端
        /// </summary>
        /// <param name="ar"></param>
        public void ClientAccepted(IAsyncResult ar)
        {
            try
            {
                var socketServer = ar.AsyncState as Socket;

                //这就是客户端的Socket实例,我们后续可以将其保存起来
                var socketClient = socketServer.EndAccept(ar);    
                AddClient(socketClient);

                //接收客户端的消息(这个和在客户端实现的方式是一样的)                
                StateObject so = new StateObject();
                so.workSocket = socketClient;
                socketClient.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReceiveMessage), so);

                //准备接受下一个客户端请求
                socketServer.BeginAccept(new AsyncCallback(ClientAccepted), socketServer);
            }
            catch (Exception ex)
            {
                HYTLogging.NCLogger.GetInstance().WriteInfoLog(ex.Message + ex.StackTrace);
            }
        }
    }

    public class StateObject


    {
        public Socket workSocket = null;
        public EndPoint tempRemoteEP = null;
        public const int BUFFER_SIZE = 1024;
        public byte[] buffer = new byte[BUFFER_SIZE];       
    }


[解决办法]
当客户端连接上服务器以后  你发送的时候还要用连接的那个tcpclient去发送消息
而不是重新实例化一个新的tcpclient 你所说的嵌套报错应该是在没有断开的情况下又重新连接了  
端口号还用的是同一个

热点排行