本帖最后由 funxu 于 2011-08-18 11:28:42 编辑

解决方案 »

  1.   

    因为代码比较长怕各位领导没耐心,呵呵,那我就先说一下,简单的异步连接,客户端发送完毕断开,但是发现有时会出现意外"System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host
       at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
       at ConsoleApplication1.AsynchronousClient.ReceiveCallback(IAsyncResult ar) in
     D:\funxu\c#\??socke(?????)\??socketclient\ConsoleApplication1\Program.cs:line 1
    35"
    因为初学C#里的socket想问的问题比较多,呵呵,我知道一般大牛不在乎这点分,不过如果有人愿意帮忙分好说
    以下为代码-客户端
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Threading;
    using System.Net;namespace ConsoleApplication1
    {
            public class StateObject
            {
                public Socket workSocket = null;
                public const int BufferSize = 256;
                public byte[] buffer = new byte[BufferSize];
                public StringBuilder sb = new StringBuilder();
            }        public class AsynchronousClient
            {
                private const int port = 6600;
                private static ManualResetEvent connectDone = new ManualResetEvent(false);
                private static ManualResetEvent sendDone = new ManualResetEvent(false);
                private static ManualResetEvent receiveDone = new ManualResetEvent(false);
                private static String response = String.Empty;
                private static void StartClient()
                {
                    try
                    {
                        IPAddress ipAddress = IPAddress.Parse("172.25.184.86");
                        IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
                        Socket client = new Socket(AddressFamily.InterNetwork,
                        SocketType.Stream, ProtocolType.Tcp);
                        client.BeginConnect(remoteEP,new AsyncCallback(ConnectCallback), client);
                        connectDone.WaitOne();
                        Send(client, "This is a test<EOF>");
                        sendDone.WaitOne();
                        Receive(client);
                        receiveDone.WaitOne();
                        Console.WriteLine("Response received : {0}", response);
                        client.Shutdown(SocketShutdown.Both);
                        client.Close();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }            private static void ConnectCallback(IAsyncResult ar)
                {
                    try
                    {
                        Socket client = (Socket)ar.AsyncState;
                        client.EndConnect(ar);
                        Console.WriteLine("Socket connected to {0}",
                            client.RemoteEndPoint.ToString());
                        connectDone.Set();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }            private static void Receive(Socket client)
                {
                    try
                    {
                        StateObject state = new StateObject();
                        state.workSocket = client;
                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReceiveCallback), state);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }            private static void ReceiveCallback(IAsyncResult ar)
                {
                    try
                    {
                        StateObject state = (StateObject)ar.AsyncState;
                        Socket client = state.workSocket;
                        int bytesRead = client.EndReceive(ar);                    if (bytesRead > 0)
                        {
                            state.sb.Append(Encoding.Unicode.GetString(state.buffer, 0, bytesRead));
                            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                new AsyncCallback(ReceiveCallback), state);
                        }
                        else
                        {
                            if (state.sb.Length > 1)
                            {
                                response = state.sb.ToString();
                            }
                            receiveDone.Set();
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }            private static void Send(Socket client, String data)
                {
                    byte[] byteData = Encoding.Unicode.GetBytes(data);
                    client.BeginSend(byteData, 0, byteData.Length, 0,
                        new AsyncCallback(SendCallback), client);
                }            private static void SendCallback(IAsyncResult ar)
                {
                    try
                    {
                        Socket client = (Socket)ar.AsyncState;
                        int bytesSent = client.EndSend(ar);
                        Console.WriteLine("Sent {0} bytes to server.", bytesSent);
                        sendDone.Set();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }
                    static void Main(string[] args)
                {
                    int i = 0;
                    try
                    {
                        for (i = 0; i < 50; i++)
                        {
                            Thread.Sleep(500);
                            Thread clientsockets = new Thread(new ThreadStart(StartClient));
                            clientsockets.Start();
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    Console.WriteLine("thread has finish at" + i.ToString());
                    Console.ReadLine();
                }
            }
        }
      

  2.   

    服务端
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    using System.Threading;
    using System.Runtime.InteropServices;namespace ConsoleApplication1
    {
        public class StateObject
        {
            public Socket workSocket = null;
            public const int BufferSize = 1024;
            public byte[] buffer = new byte[BufferSize];
            public StringBuilder sb = new StringBuilder();
        }    public class AsynchronousSocketListener
        {
            public static ManualResetEvent allDone = new ManualResetEvent(false);
            public AsynchronousSocketListener()
            {
            }        public static void StartListening()
            {
                byte[] bytes = new Byte[1024];
                IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
                IPAddress ipAddress = IPAddress.Any;
                IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 6600);
                Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    listener.Bind(localEndPoint);
                    listener.Listen(100);                while (true)
                    {
                        allDone.Reset();
                       Console.WriteLine("Waiting for a connection...");
                        listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
                        allDone.WaitOne();
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }            Console.WriteLine("\nPress ENTER to continue...");
                Console.Read();
            }        public static void AcceptCallback(IAsyncResult ar)
            {
                allDone.Set();
                Socket listener = (Socket)ar.AsyncState;
                Socket handler = listener.EndAccept(ar);
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReadCallback), state);
            }
            public static void ReadCallback(IAsyncResult ar)
            {
                String content = String.Empty;
                StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;
                int bytesRead = handler.EndReceive(ar);
                if (bytesRead > 0)
                {
                    state.sb.Append(Encoding.Unicode.GetString(state.buffer, 0, bytesRead));
                    content = state.sb.ToString();
                    if (content.IndexOf("<EOF>") > -1)
                    {
                        Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",content.Length, content);
                        Send(handler, content);
                    }
                    else
                    {
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReadCallback), state);
                    }
                }
            }        private static void Send(Socket handler, String data)
            {
                byte[] byteData = Encoding.Unicode.GetBytes(data);
                handler.BeginSend(byteData, 0, byteData.Length, 0,new AsyncCallback(SendCallback), handler);
            }        private static void SendCallback(IAsyncResult ar)
            {
                try
                {
                    Socket handler = (Socket)ar.AsyncState;
                    int bytesSent = handler.EndSend(ar);
                    Console.WriteLine("Sent {0} bytes to client.", bytesSent);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            public static int Main(String[] args)
            {
                StartListening();
                return 0;
            }
        }
    }
      

  3.   

    问题如下
    1 以上代码是我在网上找的好的一个异步socket例子了,至少可以运行,错误也不多,但是不知道一般异步socket都应该注意哪些错误处理(因为以前用delphi写socket都是事件驱动的,有意外直接在socket的exception里处理即可)
    2 "System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host
       at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
       at ConsoleApplication1.AsynchronousClient.ReceiveCallback(IAsyncResult ar) in
      D:\funxu\c#\??socke(?????)\??socketclient\ConsoleApplication1\Program.cs:line 1
    35" 这个意外的原因我判断不出来为什么
    3 上面的代码有哪些地方可以继续完善,还望各位大侠不吝赐教,拜谢~拜谢~
      

  4.   

    应该怎么编程我就不多说了(按说根本不应该用阻塞方式),单就你的程序思路而言,你的服务器受到了消息会立刻返回消息,而你的客户端则是异步Receive,同时发送了消息会立刻Shutdown,这就造成了矛盾。假设是短连接,你的客户端Send消息之后才Receive(而不是在Send之前就开始异步Receive),并且在Receive到结束标志时才Shutdown和Close,这就跟服务器的响应规范有个配合。假设是长连接,即服务器可能异步处理消息然后异步返回消息,或者即使是短连接但是客户端也不等待服务器返回数据,客户端采取异步Receive的方式,那么你可以设置一个 bool isClosing标志,在客户端关闭连接时首先置这个标志为true,而异步Receive中在 EndReceive之前首先检查这个标志,如果是true就不必执行EndReceive了。另外,并发程序天生地就会有更多设计冲突,认为现在的编程人员基本上都没有在学校里接受过这方面的设计思路的训练,所以编写的程序肯定比顺序程序的bug要多很多倍。异步操作有很多类似这种退出机制你没有设计好,这是可以理解的,所以只要在表现层捕获异常并且打印出提示就好了,其实这类提示对使用者来说也没有实质上的影响,只是看到这个提示有点心神不宁而已。
      

  5.   

    其实这个程序是从某人博客里摘抄的,稍微改了改,据说是微软官方给socket异步的例子,汗........
    这年头学习不易啊,唉~"假设是长连接,即服务器可能异步处理消息然后异步返回消息,或者即使是短连接但是客户端也不等待服务器返回数据,客户端采取异步Receive的方式,那么你可以设置一个 bool isClosing标志,在客户端关闭连接时首先置这个标志为true,而异步Receive中在 EndReceive之前首先检查这个标志,如果是true就不必执行EndReceive了。"这句非常受教
    关于这点想请问下1 按照大侠给的思路总结一下 一般异步socket如果不是阻塞模式客户端想主动断开连接的话,那应该至少有三个线程,一个接受,一个发送,一个判断状态,如果另两个完成工作则断开,是这样么?但是如果其中一个出现异常,那我该如何处理该异常呢?例如接收死锁了,那么我该如何断开客户端又不引起异常呢?2 那么如果异步不适用阻塞,那感觉同步顺序阻塞模式的读写应该完全可以满足需求了,是这样么?3 异步操作有很多类似这种退出机制你没有设计好,其实学校里根本没教,我是在自学,呵呵,不好意思,能否告知如何设计退出模式呢,如果说起来麻烦给个思路也可以啊~灰常感谢
      

  6.   

    突然想到了超时机制,那么我就在客户端记录连接时间,receive或者send超时即断开,之后内部捕获意外不显示,不过服务端也要相应的做连接状态判断,同样也是状态判断线程负责清理意外的客户端连接,那么就有必要在服务端也加上心跳了,可是这样似乎代码风格又向长连接风格转换了?我一直以为短连接socket把各种错误处理放在客户端最好,服务端尽量简单化,好像貌似不是这样啊