Чат сервер на C#
От: Polion  
Дата: 28.03.07 08:35
Оценка:
Уважаемые прошу помощи и совета.
Недавно начал изучать C# немного разобравшись с основами решил заняться сетями. Поэксперементировав с передачей данных начал делать чат. Вот код
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Net.NetworkInformation;

namespace TestServ
{
    class ClientInfo
    {
        public Socket _socket;
        public string _Name;
    }

    class Program
    { 
        public ArrayList clientList= new ArrayList();
        Socket serverSocket;
        byte[] dataByte = new byte[1024];
        private void StartServer()
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 10000);
            serverSocket.Bind(ipep);
            serverSocket.Listen((int)SocketOptionName.MaxConnections);
            serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Server start \nWaiting for connection...");
            Console.ResetColor();
        }
        private void OnAccept(IAsyncResult ar)
        {
            try
            {
                Socket clientSocket = serverSocket.EndAccept(ar);
                serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
                Console.WriteLine(clientSocket.RemoteEndPoint.ToString());
                clientSocket.BeginReceive(dataByte, 0, dataByte.Length, SocketFlags.None,
                   new AsyncCallback(OnReceived), clientSocket);                
            }
            catch (Exception ex) { Console.WriteLine(ex.ToString()); }
        }
        private void OnReceived(IAsyncResult ar)
        {
            try
            {
                int stat = 0;
                Socket clientSocket = (Socket)ar.AsyncState;
                clientSocket.EndReceive(ar);
                byte[] message1;
                Data strReceved = new Data(dataByte);
                int what = strReceved.cmdCommand;
                switch (what)
                {
                   case 0://Logon
                       try
                       {
                           char[] s;
                           string Name = "";
                           int ss = strReceved.sh+1;
                           s = Encoding.Default.GetChars(dataByte);
                           while (s[ss] != '\n')
                           {
                               Name += s[ss];
                               ss++;
                           }
                                    stat = IsClient(clientSocket,Name);
                                    if (stat != 4)
                                    {
                                        ClientInfo clientInf = new ClientInfo();
                                        clientInf._socket = clientSocket;
                                        clientInf._Name = Name;
                                        clientList.Add(clientInf);
                                        Console.WriteLine("Name " + Name);
                                        message1 = Encoding.Default.GetBytes("login\0 Connect \0");
                                        clientSocket.BeginSend(message1, 0, message1.Length, SocketFlags.None,
                                            new AsyncCallback(OnSend), clientSocket);
                                    }
                                    else
                                    {
                                        what = 4;
                                        Console.WriteLine("Попытка повторного подключения с IP: " + clientSocket.RemoteEndPoint.ToString() + "\n \t соединение принудительно разорвано");
                                    }
                       }
                       catch (Exception ex)
                       {
                           Console.WriteLine(ex.ToString());
                       }
                       break; 

                    case 1://SendAll
                        try
                        {
                            Console.WriteLine("SendAll");
                            string msgee = "";
                            char[] meee;
                            meee = Encoding.Default.GetChars(dataByte);
                            int ss2 = strReceved.sh + 1;
                            while (meee[ss2] != '\n')
                            {
                                msgee += meee[ss2];
                                ss2++;
                            }
                            message1 = Encoding.Default.GetBytes("All\0" + msgee.ToString() + "\0");
                            Console.WriteLine(msgee);
                            foreach (ClientInfo ci in clientList)
                            {
                                    ci._socket.BeginSend(message1, 0, message1.Length, SocketFlags.None,
                                            new AsyncCallback(OnSend), ci._socket);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.ToString());
                        }
                       break;
                    case 2://отправить сообщение в приват
                        try
                        {
                            char[] s1;
                            string _PName = "";
                            string _Pmsg = "";
                            int ss1 = strReceved.sh + 1;
                            s1 = Encoding.Default.GetChars(dataByte);
                            while (s1[ss1] != '\n')
                            {
                                _PName += s1[ss1];
                                ss1++;
                            }
                            ss1++;
                            while (s1[ss1] != '\n')
                            {
                                _Pmsg += s1[ss1];
                                ss1++;
                            }
                            Console.WriteLine(_PName + " : " + _Pmsg);
                            message1 = Encoding.Default.GetBytes("All\0" + _Pmsg.ToString() + "\0");
                            foreach (ClientInfo inf in clientList)
                            {
                                if (_PName == inf._Name)
                                {
                                    inf._socket.BeginSend(message1, 0, message1.Length, SocketFlags.None,
                                        new AsyncCallback(OnSend), inf._socket);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.ToString());
                        }
                        break;

                    case 4: //Plaer Logout         
                        ClientDisconnect(clientSocket);   
                        break;
               }
               if (what != 4)
               {
                   clientSocket.BeginReceive(dataByte, 0, dataByte.Length, SocketFlags.None,
                              new AsyncCallback(OnReceived), clientSocket);
               }
            }
            catch(Exception ex){Console.WriteLine(ex.ToString());}
        }
//Проверка налчия клиента в массиве игроков
       public int IsClient(Socket sock, String Name)
        {
            int stat = 0;
              foreach (ClientInfo client in clientList)
               {
                   if (client._Name ==Name.ToString())
                   {
                       Console.ForegroundColor = ConsoleColor.Red;
                       Console.WriteLine("Пользователь уже на сервере: " + sock.RemoteEndPoint.ToString());
                       Console.ResetColor();
                       byte[] message1 = Encoding.Default.GetBytes("login\0error\0");
                       sock.BeginSend(message1, 0, message1.Length, SocketFlags.None,
                           new AsyncCallback(OnSend), sock);
                       stat = 4;
                   }
               }
               return stat;
        }
//Отключение слиентов от сервера
        private void ClientDisconnect(Socket sock)
        {
             int nIndex = 0;
                            foreach (ClientInfo client in clientList)
                            {
                                if (client._socket == sock)
                                {
                                    clientList.RemoveAt(nIndex);
                                    break;
                                }
                                ++nIndex;
                            }
                            Console.WriteLine("клиент " + sock.RemoteEndPoint.ToString() + " отключился");
                            sock.Close();
        }
        private void OnSend(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                client.EndSend(ar);
            }
            catch (Exception ex) { Console.WriteLine(ex.ToString()); }
        }

        static void Main(string[] args)
        {
            Program pr = new Program();
            Thread Potok = new Thread(new ThreadStart(pr.StartServer));
            Potok.Start();
            Console.ReadLine();
        }
    }
    class Data
    {
        public Data()
        {
            this.cmdCommand = 0;
        }
      public  int sh = 0;
        public Data(byte[] data)
        {  
            string code="";
            string i = Encoding.Default.GetString(data);
            while (i[sh] != '\n')
            {
                code+=Convert.ToString(i[sh]);
                sh++;
            }
            this.cmdCommand = Convert.ToInt32(code);
        }
        public int cmdCommand;
    }
}

Суть проблемы в следующем не получается нормально обрабатывать разрыв соединения клиентом (если он неправильно завершил соединение), как правильно реализовать проверку по TimeOut клиентов. Да вообще хотелось бы услышать рекомендации как лучше сделать и что исправить .
PS: Код наверное жутко кривой но это все только из за того что программировать начал учиться совсем недавно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.