• c#socket TCP同步网络通信


    一、socket简介

      socket就是套接字,它是引用网络连接的特殊文件描述符,由三个基本要素组成:

        1: AddressFamily(网络类型)

        2: SocketType(数据传输类型)

        3:ProtocolType(采用的网络协议)

      下面是可用于IP通信的套接字组合及其常用的属性和方法

    二、socket与网络通信 

      IP连接领域有两种通信类型:面向连接的和无连接的,这里我要讲的是面向连接的,使用TCP协议来建立两个IP的值端点之间的会话,下面是它的基本步骤。

        a:建立一个套接字

        b:绑定本机的IP和端口

        c:使用listen()方法监听别人发过来的东西

        d:如果监听到连接,则可以使用Send/Receive来执行操作

        e:完成后使用Close()方法进行关闭

      工作原理如图所示:

      

    三、一个简单的同步通信示例

      下面的例子中,服务器向所有连接的客户端发送消息,实现多播功能

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    
    namespace ServerFinally
    {
        class Program
        {
            //定义两个链表,分别存储连接的客户端和断开的客户端信息类
            //并不是一个socket,而是自己写的一个辅助类
            public static List<ClientCon> connectSockets = new List<ClientCon>();   
            public static List<ClientCon> disConnectSockets = new List<ClientCon>();
            static void Main(string[] args)
            {
                //通过dns类获取本机ip地址(也可以直接输入IP地址)
                IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
                IPAddress ipaddress = ipHostInfo.AddressList[2];
                IPEndPoint ipe = new IPEndPoint(ipaddress, 9999);
    
                Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                try
                {
                    listener.Bind(ipe);
                    listener.Listen(10);
    
                    //死循环 一直等待客户端连接
                    while (true)
                    {
                        Console.WriteLine("Wait for a connnect...");
                        Socket client = listener.Accept();  //阻塞当前线程
                        Console.WriteLine("A client is connct...");
    
                        //每次连接一个客户端,将其加入链表
                        ClientCon clientCon = new ClientCon(client);
                        connectSockets.Add(clientCon);
    
                        //开启线程调用接受消息方法,一直接受消息
                        Thread t = new Thread(clientCon.ReceiveMessage);
                        t.Start();
    
                        Console.WriteLine("Start receive");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    
            //广播消息,将信息发送至所有已连接的客户端
            public static void BroadcastMessage(string data)
            {
                foreach (ClientCon client in connectSockets)
                {
                    //判断链表中的客户端是否已经断开,未断开连接就向其发送消息,否则从中移除
                    if (client.IsConnected)
                    {
                        client.SendMessage(data);
                    }
                    else
                    {
                        disConnectSockets.Add(client);
                    }
                }
    
                foreach (ClientCon disConnect in disConnectSockets)
                {
                    connectSockets.Remove(disConnect);
                }
            }
        }
    }
    服务端
    using System;
    using System.Collections.Generic;
    using System.Net.Sockets;
    using System.Text;
    
    namespace ServerFinally
    {
        /// <summary>
        /// 客户端连接辅助类
        /// </summary>
        class ClientCon
        {
            Socket client;
    
            //判断当前客户端是否断开连接
            public bool IsConnected
            {
                get;
                set;
            }
    
            //构造函数 调用的时候为cliet赋值
            public ClientCon(Socket s)
            {
                client = s;
                IsConnected = true;
            }
    
            //接受客户端发送的信息
            public void ReceiveMessage()
            {
                byte[] buffer = new byte[1024];
                string data = "";
    
                while (true)
                {
                    try
                    {
                        //判断客户端是否断开连接
                        if (!client.Poll(10, SelectMode.SelectRead))
                        {
                            int length = client.Receive(buffer);
                            data = Encoding.UTF8.GetString(buffer, 0, length);
                            if (data != "")
                            {
                                Console.WriteLine("Receive message is :" + data);
                                Program.BroadcastMessage(data);
                            }
                        }
                        else
                        {
                            IsConnected = false;
                            Console.WriteLine("A client is disconnect");
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
    
            //发送消息
            public void SendMessage(string data)
            {
                byte[] buffer = new byte[1024];
                buffer = Encoding.UTF8.GetBytes(data);
                client.Send(buffer);
            }
        }
    }
    服务器端辅助类
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    
    namespace ClientFinally
    {
        class Program
        {
            static Socket client;
            static Thread t;
            static void Main(string[] args)
            {
                //通过IP地址和端口定义一个IPEndPoint类
                IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("10.128.119.68"), 9999);
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                try
                {
                    //连接服务器
                    client.Connect(ipe);
                    Console.WriteLine("Connnect to {0}", client.RemoteEndPoint.ToString());
    
                    //开启线程 接收消息
                    t = new Thread(ReceiveMessage);
                    t.Start();
    
                    //通过死循环发送消息
                    while (true)
                    {
                        byte[] bytes = new byte[1024];
                        Console.WriteLine("Please input you message:");
                        string mes = Console.ReadLine();
    
                        //如果输入的内容为空 关闭此客户端
                        if (mes == "")
                        {
                            client.Shutdown(SocketShutdown.Both);
                            client.Close();
                            break;
                        }
                        bytes = Encoding.UTF8.GetBytes(mes);
    
                        //发送消息
                        client.Send(bytes);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
    
            //接收消息
            private static void ReceiveMessage()
            {
                while (true)
                {
                    try
                    {
                        byte[] buffer = new byte[1024];
                        //length为接收信息长度
                        int length = client.Receive(buffer);
                        if (length > 0)
                        {
                            Console.WriteLine("receive message:" + Encoding.UTF8.GetString(buffer));
                        }
                    }
                    catch
                    {
                        break;
                    }
                }
            }
        }
    }
    客户端代码

    先启动服务器端,在启动客户端,效果如下

      

  • 相关阅读:
    跟vczh看实例学编译原理——二:实现Tinymoe的词法分析
    跟vczh看实例学编译原理——一:Tinymoe的设计哲学
    跟vczh看实例学编译原理——零:序言
    2013年终总结
    如何设计一门语言(十二)——设计可扩展的类型
    开始用Word 2013来写博客
    如何设计一门语言(十一)——删减语言的功能
    如何设计一门语言(十)——正则表达式与领域特定语言(DSL)
    链表
    结构的学习
  • 原文地址:https://www.cnblogs.com/forever-Ys/p/10085799.html
Copyright © 2020-2023  润新知