【.Net】Socket小示例

引言

     项目中用到了Socket,这里做个控制台小示例记录一下。

Client

    客户端的Receive用了异步方法,保持长连接,可以随时发送消息和响应服务端的消息,如下

        static string ClientReceiveMessage = "";
        static byte[] receivedBytes = new byte[1024];
        static void Main(string[] args)
        {
           
            IPHostEntry ipHost = Dns.Resolve("127.0.0.1");
            IPAddress ipAddress = ipHost.AddressList[0];
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 2012);

            string sendingMessage = "Hello World Socket Test";

            Console.WriteLine("Creating message: Hello World Socket Test");


            Socket sender = new Socket(AddressFamily.InterNetwork,
                                   SocketType.Stream,
                                   ProtocolType.Tcp);
            sender.Connect(ipEndPoint);
          
            sender.BeginReceive(receivedBytes, 0, receivedBytes.Length, 0, ReceiveCallback, sender);

            while (true)
            {
                sendingMessage = Console.ReadLine();
                byte[] forwardMessage = Encoding.ASCII.GetBytes(sendingMessage + "[FINAL]");
                sender.Send(forwardMessage);
            }
        }

        private static void ReceiveCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;

            int totalBytesReceived = client.EndReceive(ar);

            if (totalBytesReceived > 0)
            {
              
                ClientReceiveMessage += Encoding.ASCII.GetString(receivedBytes, 0, totalBytesReceived);
               if (ClientReceiveMessage.IndexOf("[FINAL]", StringComparison.Ordinal) > -1)
                {
                    Console.WriteLine(ClientReceiveMessage);
                    ClientReceiveMessage = "";
                }   
 
                client.BeginReceive(receivedBytes, 0, receivedBytes.Length, 0, new AsyncCallback(ReceiveCallback), client);
            }
            else
            {
                Console.WriteLine("服务端结束不再发送消息!" );
                ClientReceiveMessage = "";
            }

        }

Server

      服务端循环异步Accept,可以接收多个client消息,并且马上回复。

        static ManualResetEvent allDone = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            
            Socket listener = new Socket(AddressFamily.InterNetwork,
                                         SocketType.Stream,
                                         ProtocolType.Tcp);
            listener.Bind(new IPEndPoint(IPAddress.Any, 2012));
            listener.Listen(1);

            while (true)
            {
                allDone.Reset();
listener.BeginAccept(ar => { allDone.Set(); Socket MyServer = (Socket)ar.AsyncState; Socket service = MyServer.EndAccept(ar); byte[] receivedBytes = new byte[1024]; while (true) { string receivedValue = string.Empty; int numBytes = service.Receive(receivedBytes); receivedValue += Encoding.ASCII.GetString(receivedBytes,0, numBytes); if (receivedValue.IndexOf("[FINAL]", StringComparison.Ordinal) > -1) { Console.WriteLine("Received value: {0} from " + service.RemoteEndPoint, receivedValue); string replyValue = "Message successfully received.[FINAL]"; byte[] replyMessage = Encoding.ASCII.GetBytes(replyValue); service.Send(replyMessage); } } }, listener); allDone.WaitOne(); }

注意事项

       1.Socket的Receive方法响应次数,是以缓冲数组的大小划分。如果数组大小为1024,消息为2048,Receive将会触发两次。作为接收方无法通过Receive来确定是否已完整接收,所以要对消息另作处理,例如在消息中增加[FINAL]来确定消息已发送完毕。

       2.如果没有消息发送,接收方Receive方法会一直等待。但如果发送方调用Shutdown(SocketShutdown.Send)方法,接收方的Receive会马上返回0,所以在非来回传递消息的情况下,可以Shutdown方法来实现消息发送完毕。

       3.可以设置ReceiveTimeout的值,超时会抛出异常,然而只能作用于Receive方法,对BeginReceive无效。

       

原文地址:https://www.cnblogs.com/caizl/p/4984633.html