现在的问题是,假如有四个客户端连接服务器,向服务器发送信息,服务器接收后,分别把信息转发给其他三个客户端。
转发这块总是出错。
使用Tcpclient 和Ticplistener 实现。
重点是多线程设计,希望给我个详细的代码示例。谢谢

解决方案 »

  1.   

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Finstone.IM.Common;
    using System.Collections;
    using System.Data;namespace Finstone.IM.Core
    {
        /// <summary>
        /// 连接管理器
        /// </summary>
        public class ConnectionManager
        {        static private Dictionary<int, LoginUser> _OnLineUsers = new Dictionary<int, LoginUser>();
            static private Hashtable ht = new Hashtable();
            static ConnectionManager()
            {
                
            }        public static Dictionary<int, LoginUser> OnLineUsers
            {
                get { return _OnLineUsers; }
            }
            /// <summary>
            /// 处理一个新的入站连接
            /// </summary>
            /// <param name="conn"></param>
            static public void OnNewConnection(Connection conn)
            {
                Console.WriteLine("用户开始进入系统");
                conn.Disconnect += new Connection.DisconnectHandler(OnDisconnect);
                conn.Error += new Connection.ErrorHandler(OnError);
                //
                //为入站连接建立一个新的入站处理
                LoginUser login = new LoginUser(conn);
                login.OnLoginSuccess += new UserLoginNotify(login_OnLoginSuccess);
                login.OnLogout += new UserLogoutNotify(login_OnLogout);
                if(ht.ContainsKey(conn.Identity))
                     ht.Add(conn.Identity, conn);           
            }
            //退出登录
            static void login_OnLogout(object sender, LogoutNotifyEventArg e)
            {
                //向所有在线用户发出下线通知
                OnOffLinePacket p = new OnOffLinePacket(e.UserName, "","", e.UserID, "", 0);
                ConnectionManager.SendToAll(e.UserID, p);
                e.Conn.Close();
                OnDisconnect(e.Conn);
                Console.Write("用户:--" + e.Conn.Identity + " 退出系统");
            }
            /// <summary>
            /// 用户登录成功后的处理
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            static void login_OnLoginSuccess(object sender, LoginNotifyEventArg e)
            {
                Console.WriteLine("用户:-- "+ e.UserId +"进入系统");
                    LoginUser user = (LoginUser)sender;
                    //获取所有人员列表
                   //发送在线用户列表
                   StringBuilder s =new StringBuilder() ;
                   s.Append("<Users>");
                    lock(_OnLineUsers)
                    {
                        foreach (KeyValuePair<int, LoginUser> kvp in _OnLineUsers)
                        {
                            s.Append("<User><Name>" + kvp.Value.UserName + "</Name><UserCode>" + kvp.Value.UserCode + "</UserCode><UserRole>" + kvp.Value.UserRole + "</UserRole><UserID>" + kvp.Value.UserID + "</UserID><IP>" + e.IP + "</IP><Port>" + e.Port + "</Port></User>");
                        }
                    }
                   s.Append("</Users>");
                   OnLineUsersPacket users = new OnLineUsersPacket(s.ToString());
                   user.Connection.Send(users);            
                //登录成功后,分别向列表中的原有用户进行通知
                OnOffLinePacket online = new OnOffLinePacket(e.UserName,e.UserCode,e.UserRole,e.UserId, e.IP, e.Port);
                lock (_OnLineUsers)
                {
                    foreach (int un in _OnLineUsers.Keys)
                    {
                        _OnLineUsers[un].Connection.Send(online);
                    }
                }
                //将LoginUser放到列表中
                if (_OnLineUsers.ContainsKey(e.UserId))
                {
                    _OnLineUsers.Remove(user.UserID);            }
                _OnLineUsers.Add(user.UserID, user); //放到在线
                if (ht.ContainsKey(user.UserID))
                {
                    ht.Remove(user.UserID);
                }            Console.WriteLine("当前用户数为:" + _OnLineUsers.Count.ToString());
            }        /// <summary>
            /// 断开连接处理
            /// </summary>
            /// <param name="conn"></param>
            static private void OnDisconnect(Connection conn)
            {
                Console.WriteLine("断开连接" + conn.Identity);
                lock (_OnLineUsers)
                {
                    if (conn.Identity != 0)
                    {
                        //从在线列表中移
                        if (_OnLineUsers.ContainsKey(conn.Identity))
                        {
                            _OnLineUsers.Remove(conn.Identity);
                            conn.Identity = 0;
                        }
                    }
                }
            }        //连接错误处理
            static private void OnError(Connection conn, string err)
            {
                try
                {
                    Console.WriteLine("用户连接"+conn.Identity +"出错: {0}", err);
                    if (_OnLineUsers.ContainsKey(conn.Identity))
                    {
                        LoginUser u = _OnLineUsers[conn.Identity];
                        OnOffLinePacket p = new OnOffLinePacket(u.UserName, "", "", u.UserID, "", 0);
                        SendToAll(u.UserID, p);
                    }
                   
                }
                catch(Exception ex)
                {
                    Console.WriteLine("连接出错,无法释放连接:{0}", ex.Message);
                }
            }
            /// <summary>
            /// 向所有在线用户发送信息
            /// </summary>
            /// <param name="packet"></param>
            static public void SendToAll(int  FromUser,PacketBase packet)
            {
                try
                {
                    lock (_OnLineUsers)
                    {
                        foreach (KeyValuePair<int, LoginUser> kvp in _OnLineUsers)
                        {
                            if (kvp.Key != FromUser)
                                kvp.Value.Connection.Send(packet);                    }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("群发信息出错:{0}", ex.Message);
                }
            }
            /// <summary>
            /// 发送给某个用户
            /// </summary>
            /// <param name="username"></param>
            /// <param name="packet"></param>
            static public void Send(int uid,PacketBase packet)
            {
                try
                {
                    GetUserConnection(uid).Send(packet);
                }
                catch(Exception ex)
                {
                    Console.WriteLine("发送信息出错:{0}", ex.Message);
                }
            }        static private Connection GetUserConnection(int uid)
            {
                lock (_OnLineUsers)
                {
                    if (_OnLineUsers.ContainsKey(uid))
                    {
                        return _OnLineUsers[uid].Connection;
                    }
                    else
                        return null;
                }
            }
              }
    }
      

  2.   

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.Collections;namespace Server
    {
        class Program
        {
            
            static void Main(string[] args)
            {            Thread mainthread = new Thread(new ThreadStart(start));
                mainthread.Start();
                Console.Read();
            }
            public static void start()
            {
                TcpListener tc = new TcpListener(IPAddress.Parse("127.0.0.1"), 7788);
                tc.Start(5);
               
                    while (tc.Pending() == false)
                        Thread.Sleep(1000);
                  
                        SenInfo(tc);
                
                    
                
            }
            public static void  SenInfo(TcpListener tl)
            {
                Listener ls = new Listener(tl);
                Thread t = new Thread(new ThreadStart(ls.si));
                Thread send = new Thread(new ThreadStart(ls.Send));
                t.Start();
                send.Start();
            }
        }    class Listener
        { 
            ArrayList alist_thread;
          
            TcpListener newtl;
     
            public Listener(TcpListener ne)
            {
                
                alist_thread = new ArrayList();
                newtl = ne;
               
            }
            public void si()
            {
                lock (alist_thread)
                {
                    TcpClient tc = newtl.AcceptTcpClient();
                    alist_thread.Add(tc);
                }
            }
            public void Send()
            {
                               while (alist_thread.Count < 3)
                        Thread.Sleep(1000);
                            string nihao = "nihao";
                            byte[] bytes = new byte[500];
                            bytes = Encoding.Unicode.GetBytes(nihao);
                            TcpClient tcl;
                            for (int i = 0; i < alist_thread.Count; i++)
                            {
                                tcl = (TcpClient)alist_thread[i];
                                NetworkStream myns = tcl.GetStream();
                                myns.Write(bytes, 0, bytes.Length);
                            }
                            
                }
            }
        }这是我做的一个例子,同时运行多个客户端时 ,只有 第一个连接被添加到alist_thread列表里了,以后就不再执行alist_thread.Add(tc)了,为什么呢 ???
      

  3.   

    4楼辛苦了,可那不是 tcpclient 和tcplitener 啊 
      

  4.   

    问题解决了啊 ,呵呵,郁闷,为什么每次问问题最后都是自己解答的呢?
    但还得给分啊 ,using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Net; 
    using System.Net.Sockets; 
    using System.Threading; 
    using System.Collections; namespace Server 

        class Program 
        { 
            
            static void Main(string[] args) 
            {             Thread mainthread = new Thread(new ThreadStart(start)); 
                mainthread.Start(); 
                Console.Read(); 
            } 
            public static void start() 
            { 
                TcpListener tc = new TcpListener(IPAddress.Parse("127.0.0.1"), 7788); 
                tc.Start(5); 
              while(true)
               {
                    while (tc.Pending() == false) 
                        Thread.Sleep(1000); 
                  
                        SenInfo(tc); 
                }
                    
                
            } 
            public static void  SenInfo(TcpListener tl) 
            { 
                Listener ls = new Listener(tl); 
                Thread t = new Thread(new ThreadStart(ls.si)); 
                Thread send = new Thread(new ThreadStart(ls.Send)); 
                t.Start(); 
                send.Start(); 
            } 
        }     class Listener 
        { 
            ArrayList alist_thread; 
          
            TcpListener newtl;         public Listener(TcpListener ne) 
            { 
                
                alist_thread = new ArrayList(); 
                newtl = ne; 
              
            } 
            public void si() 
            { 
                lock (alist_thread) 
                { 
                    TcpClient tc = newtl.AcceptTcpClient(); 
                    alist_thread.Add(tc); 
                } 
            } 
            public void Send() 
            { 
                              while (alist_thread.Count < 3) 
                        Thread.Sleep(1000); 
                            string nihao = "nihao"; 
                            byte[] bytes = new byte[500]; 
                            bytes = Encoding.Unicode.GetBytes(nihao); 
                            TcpClient tcl; 
                            for (int i = 0; i < alist_thread.Count; i++) 
                            { 
                                tcl = (TcpClient)alist_thread[i]; 
                                NetworkStream myns = tcl.GetStream(); 
                                myns.Write(bytes, 0, bytes.Length); 
                            } 
                            
                } 
            } 
        } 
      

  5.   

    小弟也堵在这哪位大侠有用C语言写的代码没
    并且注释一下。。小弟的cpp很罗啊