using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Drawing;
using System.Windows.Forms;
class TalkForm:Form {    
    public TalkForm(Talker talker) {
        this.talker = talker;
        talker.Notifications += new 
                Talker.NotificationCallback(HandleTalkerNotifications);
        Splitter talkSplitter = new Splitter();
        Panel talkPanel = new Panel();        
        receiveText = new TextBox();
        sendText = new TextBox(); 
        receiveText.MaxLength = sendText.MaxLength = 65536;
        statusText = new Label();
        receiveText.Dock = DockStyle.Top;
        receiveText.Multiline = true;
        receiveText.ScrollBars = ScrollBars.Both;
        receiveText.Size = new Size(506, 192);
        receiveText.TabIndex = 1;
        receiveText.Text = "";
        receiveText.WordWrap = false;
        receiveText.ReadOnly = true;
        talkPanel.Anchor = (AnchorStyles.Top|AnchorStyles.Bottom
                    |AnchorStyles.Left|AnchorStyles.Right);
        talkPanel.Controls.AddRange(new Control[] {sendText,
                    talkSplitter,
                    receiveText});
        talkPanel.Size = new Size(506, 371);
        talkPanel.TabIndex = 0;
        talkSplitter.Dock = DockStyle.Top;
        talkSplitter.Location = new Point(0, 192);
        talkSplitter.Size = new Size(506, 6);
        talkSplitter.TabIndex = 2;
        talkSplitter.TabStop = false;
        statusText.Dock = DockStyle.Bottom;
        statusText.Location = new Point(0, 377);
        statusText.Size = new Size(507, 15);
        statusText.TabIndex = 1;
        statusText.Text = "Status:";
        sendText.Dock = DockStyle.Fill;
        sendText.Location = new Point(0, 198);
        sendText.Multiline = true;
        sendText.ScrollBars = ScrollBars.Both;
        sendText.Size = new Size(506, 173);
        sendText.TabIndex = 0;
        sendText.Text = "";
        sendText.WordWrap = false;
        sendText.TextChanged += new EventHandler(HandleTextChange);
        sendText.Enabled = false;
        AutoScaleBaseSize = new Size(5, 13);
        ClientSize = new Size(507, 392);
        Controls.AddRange(new Control[] {statusText,
                    talkPanel});
        Text = "WinTalk";
    }    
    protected override void OnClosed(EventArgs e){
        if(talker!=null){
            talker.Notifications -= new 
                Talker.NotificationCallback(HandleTalkerNotifications);
            talker.Dispose();
        }
        base.OnClosed(e);
    }
    private void HandleTalkerNotifications(
        Talker.Notification notify, Object data){
        switch(notify){
        case Talker.Notification.Initialized:
            break;
        case Talker.Notification.StatusChange:
            Talker.Status status = (Talker.Status)data;
            statusText.Text = String.Format("Status: {0}", status);
            if(status == Talker.Status.Connected){
                sendText.Enabled = true;
sendText.Focus();
            }
            break;
        case Talker.Notification.ReceivedAppend:
            receiveText.AppendText(data.ToString());       
            break;
        case Talker.Notification.ReceivedRefresh:
            receiveText.Text = data.ToString();
            receiveText.SelectionStart = Int32.MaxValue;
            receiveText.ScrollToCaret();        
            break;
        case Talker.Notification.Error:            
            Close(data.ToString());        
            break;
        case Talker.Notification.End:                                    
sendText.TextChanged -= new EventHandler(HandleTextChange); 
MessageBox.Show(this, data.ToString(), "Closing WinTalk");             
            Close();
            break;
        default:
            Close();
            break;
        }
    }
    private void HandleTextChange(Object sender, EventArgs e){
        if(talker != null){
            talker.SendTalk((sender as TextBox).Text);
        }        
    }
private void InitializeComponent()
{
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(480, 273);
this.Name = "TalkForm";
}   
    private void Close(String message){   
        MessageBox.Show(message, "Error!");        
        Close();
    }
    private TextBox receiveText;        
    private TextBox sendText;    
    private Label statusText;
    private Talker talker;   
}
class App
{        
public static void Main(String[] args)
{        
if(ParseArgs(args))
{           
Talker talker = new Talker(endPoint, client);
TalkForm form = new TalkForm(talker);                   
talker.Start();
Application.Run(form);
}        
}
private static IPEndPoint endPoint;
private static bool client;
private static bool ParseArgs(String[] args)
{
try
{        
if(args.Length == 0)
{
client = false;
endPoint = new IPEndPoint(IPAddress.Any,5150);
return true;
}
if (args[0][0]!='/' && args[0][0]!='-') 
{
ShowUsage();
return false;
}
switch(Char.ToUpper(args[0][1], CultureInfo.InvariantCulture))
{
case 'L':
int port = 5150;
if(args.Length > 1)
{
port = Convert.ToInt32(args[1]);    
}
endPoint = new IPEndPoint(IPAddress.Any,port);
client = false;
break;
case 'C':
port = 5150;
String address = "127.0.0.1";
client = true;
if(args.Length > 1)
{
address = args[1];
port = Convert.ToInt32(args[2]);                                        
}                
endPoint = new IPEndPoint(Dns.Resolve(address).AddressList[0], port);
break;
default:
ShowUsage();
return false;
}
}
catch
{
ShowUsage();
return false;
}    
    
return true;
}
private static void ShowUsage()
{
MessageBox.Show("WinTalk [switch] [parameters...]\n\n"+
"  /L  [port]\t\t-- Listens on a port.  Default:  5150\n"+
"  /C  [address] [port]\t-- Connects to an address and port.\n\n"+
"Example Server - \n"+
"Wintalk /L\n\n"+
"Example Client - \n"+
"Wintalk /C ServerMachine 5150","WinTalk Usage");
}
}

解决方案 »

  1.   

    class Talker:IDisposable{
        public Talker(IPEndPoint endPoint, bool client){
            this.endPoint = endPoint;
            this.client = client;
            socket = null;
            reader = null;
            writer = null;
            statusText = prevSendText = prevReceiveText = String.Empty;
        }
        ~Talker(){
            Dispose();
        }
        public void Dispose(){        
            GC.SuppressFinalize(this);
            if(reader != null){
                reader.Close();
                reader = null;
            }
            if(writer != null){
                writer.Close();
                writer = null;
            }
            if(socket != null){
                socket.Close();
                socket = null;
            }        
        }
        public delegate void NotificationCallback(Notification notify, Object data);
        public event NotificationCallback Notifications;
        public enum Notification{
            Initialized = 1,
            StatusChange,
            ReceivedRefresh,
    ReceivedAppend,
            End,
            Error
        }
        public enum Status{
            Listening,
            Connected
        }
        public void Start(){
            ThreadPool.QueueUserWorkItem(new WaitCallback(EstablishSocket));
        }
        public void SendTalk(String newText){                
            String send;
            if((prevSendText.Length <= newText.Length) && String.CompareOrdinal(newText, 0, prevSendText, 0, prevSendText.Length)==0)
    {
                String append = newText.Substring(prevSendText.Length);
                send = String.Format("A{0}:{1}", append.Length, append);
            }
    else
    {
                send = String.Format("R{0}:{1}", newText.Length, newText);
            }   
            writer.Write(send);
            writer.Flush();
            prevSendText = newText;
        }
        private void SetStatus(Status status)
    {
            this.status = status;
            Notifications(Notification.StatusChange, status);
        }
        private void EstablishSocket(Object state){               
    NetworkStream stream = null;
            try
    {
                if(!client)
    {
                    Socket listener;
                    
                    try
    {
                        listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
                        listener.Blocking = true;
                        listener.Bind(endPoint);
                        SetStatus(Status.Listening);                    
                        listener.Listen(0);
                        socket = listener.Accept();
    listener.Close();          
    stream = new NetworkStream(socket);
    reader = new StreamReader(stream);
    writer = new StreamWriter(stream);
    writer.Write("WINTALK .NET");
    writer.Flush();
                    }
    catch(SocketException e)
    {
                        if(e.ErrorCode == 10048)
    {
                            client = true;
                            endPoint = new IPEndPoint(Dns.Resolve("127.0.0.1").AddressList[0], endPoint.Port);
                        }
    else
    {
                            Notifications(Notification.Error, "Error Initializing Socket:\n"+e.ToString());                        
                        }
                    }                                    
                }
                if(client)
    {
                    Socket temp = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                    temp.Blocking = true;
                    temp.Connect(endPoint);
                    socket = temp;
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
    stream = new NetworkStream(socket);
    reader = new StreamReader(stream);
    writer = new StreamWriter(stream);
    char[] handshake = new char[12];
    try
    {
    if (!(reader.Read(handshake,0,12)>0 && new string(handshake)=="WINTALK .NET"))
    {
    socket.Close();
    socket = null;
    }
    else
    {
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout , 0);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 0);
    }
    }
    catch
    {
    socket.Close();
    socket = null;
    }
                }
                if(socket != null)
    {
                    SetStatus(Status.Connected);                 
                    Notifications(Notification.Initialized, this);                
    ReceiveTalk();
    Notifications(Notification.End, "Remote connection has closed.");
    }
    else
    {
                    Notifications(Notification.Error, 
                        "Failed to Establish Socket, did you specify the correct port?");
                }
            }
    catch(IOException e)

                SocketException sockExcept = e.InnerException as SocketException; 
                if(sockExcept != null && 10054 == sockExcept.ErrorCode)
    {
                    Notifications(Notification.End, "Remote connection has closed.");
                }
    else
    {
    if (Notifications != null)
    Notifications(Notification.Error, "Socket Error:\n"+e.Message);
                }                
            }
    catch(Exception e)
    {              
                Notifications(Notification.Error, "Socket Error:\n"+e.Message);
            }
        }
        private void ReceiveTalk()
    {
            char[] commandBuffer = new char[20];
            char[] oneBuffer = new char[1];
            int readMode = 1;
            int counter = 0;        
            StringBuilder text = new StringBuilder();
            while(readMode != 0)
    {
                if(reader.Read(oneBuffer, 0, 1)==0)
    {
                    readMode = 0;
                    continue;
                }
    switch(readMode)
    {
                case 1:        
                    if(counter == commandBuffer.Length)
    {
                        readMode = 0;
                        continue;
                    }
                    if(oneBuffer[0] != ':')
    {
                        commandBuffer[counter++] = oneBuffer[0];
                    }
    else
    {
                        counter = Convert.ToInt32(new String(commandBuffer, 1, counter-1));
                        if(counter>0)
    {
                            readMode = 2;                            
                            text.Length = 0;
                        }
    else if(commandBuffer[0] == 'R')
    {
                            counter = 0;
                            prevReceiveText = String.Empty;
                            Notifications(Notification.ReceivedRefresh, prevReceiveText);
                        }
                    }
                    break;
                case 2:
                    text.Append(oneBuffer[0]);
                    if(--counter == 0)
    {
                        switch(commandBuffer[0])
    {
                        case 'R':
                            prevReceiveText = text.ToString();
    Notifications(Notification.ReceivedRefresh, prevReceiveText);                    
                            break;
                        default:
    string newText = text.ToString();
                            prevReceiveText += newText;
                            Notifications(Notification.ReceivedAppend, newText);                    
    break;
                        }                    
                        readMode = 1;
                    }
                    break;
                default:
                    readMode = 0;
                    continue;
                }            
            }        
        }
        private Socket socket;
        private TextReader reader;
        private TextWriter writer;
        bool client;
        IPEndPoint endPoint;
        private String prevSendText;
        private String prevReceiveText;
        private String statusText;
        private Status status;    
    }