using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;

public class Chat {

    
private static UdpClient m_Client;

    
private static int ListenerPort = 8080;
    
private static int SenderPort = 8080;
    
private static int LocalPort;
    
private static int RemotePort;

    
private static string m_szHostName;

    
private static IPAddress m_GroupAddress;
    
private static IPHostEntry m_LocalHost;
    
private static IPEndPoint m_RemoteEP;

    
private static bool m_Done = false;

    
public static void Usage() {
        Console.WriteLine(
"UDP 多路广播聊天实用工具");
        Console.WriteLine(
"\n用法::");
        Console.WriteLine(
"chat.exe");
    }


    
public static void Main( String [] args ) {

        LocalPort 
= SenderPort;
        RemotePort 
= ListenerPort;

        
if( args.Length > 0 ) {
            
//
            
// 输出帮助消息,因为此实用工具不采用任何参数
            
//
            Usage();
            
return;
        }


        m_szHostName 
= Dns.GetHostName();

        m_LocalHost 
= Dns.GetHostByName(m_szHostName);

        Console.WriteLine(
"本地端口:{0},远程端口:{1}", LocalPort, RemotePort);

        Console.WriteLine(
"正在初始化");

        Initialize();

        Console.WriteLine(
"正在启动侦听器线程");

        Thread t 
= new Thread(new ThreadStart(Listener));
        t.Start();

        Byte [] buffer 
= null;

        Encoding ASCII 
= Encoding.ASCII;

        
bool m_ShuttingDown = false;

        
while(!m_ShuttingDown) {
            String s 
= Console.ReadLine();

            
if( s.Length == 0 )
                
continue;

            
if(String.Compare(s,0,"@",0,1== 0{
                m_Done 
= true;
                
//
                
// 将结束符发送给我们自己,
                
// 以便接收线程可以关闭
                
//
                s = m_szHostName + ":@";
                m_ShuttingDown 
= true;
            }
 else {
                s 
= m_szHostName + ":" + s;
            }



            buffer 
= new Byte[s.Length + 1];
            
//
            
// 将数据发送给远程对方主机
            
//

            
int len = ASCII.GetBytes( s.ToCharArray(), 0, s.Length, buffer, 0);

            
int ecode = m_Client.Send(buffer, len, m_RemoteEP);

            
if(ecode <= 0{
                Console.WriteLine(
"发送时出错:" + ecode);
            }


        }


        t.Abort();
        t.Join();

        Console.WriteLine(
"正在关闭连接");

        Terminate();

    }
 // Main

    
public static void Terminate() {
        m_Client.DropMulticastGroup(m_GroupAddress);
    }


    
public static void Initialize() {

        
//
        
// 实例化 UdpCLient
        
//
        m_Client = new UdpClient(LocalPort);

        
//
        
// 创建多路广播组对象
        
//

        m_GroupAddress 
= IPAddress.Parse("224.0.0.1");

        
//
        
// 联接组
        
//
        try {
            m_Client.JoinMulticastGroup(m_GroupAddress, 
100);
        }
 catch(Exception) {
            Console.WriteLine(
"无法联接多路广播组");
        }


        
//
        
// 创建对方主机的终结点
        
//
        m_RemoteEP = new IPEndPoint( m_GroupAddress, RemotePort );

    }


    
public static void Listener() {

        
//
        
// 侦听器等待数据到来
        
// 并用缓冲区保存它。

        Thread.Sleep(
2000); // 确保 client2 正在接收

        Encoding    ASCII 
= Encoding.ASCII;

        
while(!m_Done) {
            IPEndPoint endpoint 
= null;
            Byte[] data 
= m_Client.Receive(ref endpoint);

            String strData 
= ASCII.GetString(data);

            
if( strData.IndexOf(":@"> 0 ) {
                
//
                
// 我们接收到一个终止指示,
                
// 现在我们必须确定它是来
                
// 自我们的主线程的关闭,
                
// 还是来自其他地方
                
//
                Char [] separators = {':'};
                String [] vars 
= strData.Split(separators);

                
if( vars[0== m_szHostName ) {
                    
//
                    
// 这是来自我们自己的线程,因此
                    
// 立即结束
                    
//
                    Console.WriteLine("正在关闭侦听器线程");

                    
//
                    
// 此过程应已由主线程完成了,但为
                    
// 安全起见,我们再执行一次
                    
//
                    m_Done = true;
                }

                
else {
                    
//
                    
// 这是来自其他地方的
                    
//
                    Console.WriteLine("{0} 已离开对话", vars[0]);
                }

            }

            
else {
                
//
                
// 这是从其他地方以及我们自己
                
// 处接收到的正常数据
                
// 在输出前,查看它是否来自我
                
// 们自己
                
//
                if(strData.IndexOf(":"> 0{
                    Char [] separators 
= {':'};
                    String [] vars 
= strData.Split(separators);

                    
if( vars[0!= m_szHostName ) {
                        Console.WriteLine(strData);
                    }

                }

            }

        }


        Console.WriteLine(
"侦听器线程已完成");
        
return;
    }

}