• Socket通信简介


      第一次做CS的程序,关于socket的,通过各种资料的搜索,其实我觉得说白了主要就分为:

      1、套结的关键字。

      2、服务器和客户机的远程通信。

      3、消息的处理。

      服务器原理

     1 //把ip地址转换为实例
     2                 IPAddress ipa = IPAddress.Parse("127.0.0.1");
     3                 //监听端口8001
     4                 TcpListener mylsn = new TcpListener(ipa, 8001);
     5                 //开启监听
     6                 mylsn.Start();
     7                 //输出监听成功的信息
     8                 Console.WriteLine("在8001启动服务,等待连接");
     9                 //等待处理接入连接请求
    10                 while (true)
    11                 {
    12                     Socket mysock = mylsn.AcceptSocket();
    13                     Console.WriteLine("有连接,连接来自" + mysock.RemoteEndPoint);
    14                     work w = new work();
    15                     w.mysock = mysock;
    16                     w.mylsn = mylsn;
    17                     Thread t = new Thread(new ThreadStart(w.main));
    18                     t.Start();
    19                 }
    View Code

      class类:

     1 class work
     2     {
     3         public Socket mysock;
     4         public TcpListener mylsn;
     5         public void main()
     6         {
     7             //接收客户端消息
     8             byte[] data = new byte[100];
     9             mysock.Receive(data);
    10             string rt = System.Text.UTF8Encoding.UTF8.GetString(data);
    11             Console.WriteLine(rt);
    12             //给客户端发消息
    13             mysock.Send(UTF8Encoding.UTF8.GetBytes("server callback"));
    14             //释放资源
    15             mysock.Close();
    16             mylsn.Stop();
    17         }
    18     }
    View Code

      客户机原理:

     1 int port = 8001;
     2                 string host = "127.0.0.1";
     3                 //创建终结点EndPoint
     4                 IPAddress ip = IPAddress.Parse(host);
     5                 IPEndPoint ipe = new IPEndPoint(ip, port);   //把ip和端口转化为IPEndPoint的实例
     6 
     7                 //创建Socket并连接到服务器
     8                 Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);   //  创建Socket
     9                 Console.WriteLine("Connecting...");
    10                 c.Connect(ipe); //连接到服务器
    11 
    12                 //向服务器发送信息
    13                 string sendStr = "Hello,this is a socket test";
    14                 byte[] bs = Encoding.ASCII.GetBytes(sendStr);   //把字符串编码为字节
    15 
    16                 Console.WriteLine("Send message");
    17                 c.Send(bs, bs.Length, 0); //发送信息
    18 
    19                 //接受从服务器返回的信息
    20                 string recvStr = "";
    21                 byte[] recvBytes = new byte[1024];
    22                 int bytes;
    23                 bytes = c.Receive(recvBytes, recvBytes.Length, 0);    //从服务器端接受返回信息
    24                 recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    25                 Console.WriteLine("client get message:{0}", recvStr);    //回显服务器的返回信息
    26 
    27                 Console.ReadLine();
    28                 //一定记着用完Socket后要关闭
    29                 c.Close();
    View Code

      命名空间:System.Net和System.Net.Sockets(通信) System.IO(消息字节处理)

      到这里,我想通信已经完整的建立了,但是有些小朋友肯定会问,这只是一个简单的客户机和主机的联系,那么,一个主机,N个客户机,又是怎么回事呢,

      服务器原理:

     1     private TcpListener myListener;
     2     myListener = new TcpListener(localAddress, port);
     3     myListener.Start();
     4 
     5     service.AddItem(string.Format("开始在{0}:{1}监听客户端连接", localAddress, port));
     6     //创建一个线程监听客户端连接请求
     7     ThreadStart ts = new ThreadStart(ListenClientConnect);//委托
     8     Thread myThread = new Thread(ts);
     9     myThread.Start();
    10     
    11     
    12      private void ListenClientConnect()
    13         {
    14             while (true)
    15             {
    16                 TcpClient newClient = null;
    17                 try
    18                 {
    19                     //等待用户进入
    20                     newClient = myListener.AcceptTcpClient();
    21                 }
    22                 catch
    23                 {
    24                     //当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常
    25                     //因此可以利用此异常退出循环
    26                     break;
    27                 }
    28                 //每接受一个客户端连接,就创建一个对应的线程循环接收客户端发来的信息
    29                 ParameterizedThreadStart pts = new ParameterizedThreadStart(ReceiveData);//委托
    30                 Thread threadReceive = new Thread(pts);
    31                 User user = new User(newClient);
    32                 threadReceive.Start(user);
    33                 userList.Add(user);
    34                 service.AddItem(string.Format("{0}进入", newClient.Client.RemoteEndPoint));
    35                 service.AddItem(string.Format("当前连接用户数:{0}", userList.Count));
    36             }
    37         }
    38     
    39      private void ReceiveData(object obj)
    40         {
    41             User user = (User)obj;
    42             TcpClient client = user.client;
    43             //是否正常退出接收线程
    44             bool normalExit = false;
    45             //用于控制是否退出循环
    46             bool exitWhile = false;
    47             while (exitWhile == false)
    48             {
    49                 //当前要传送的数据
    50                 string receiveString = null;
    51                 try
    52                 {
    53                     receiveString = user.sr.ReadLine();
    54                 }
    55                 catch (Exception ex)
    56                 {
    57                     //该客户底层套接字不存在时会出现异常
    58                     service.AddItem("接收数据失败,原因:" + ex.Message);
    59                 }
    60                 //TcpClient 对象将套接字进行了封装,如果TcpClient对象关闭了,
    61                 //但是底层套接字未关闭,并不产生异常,但是读取的结果为 null
    62                 if (receiveString == null)
    63                 {
    64                     if (normalExit == false)
    65                     {
    66                         //如果停止了监听,Connected 为 false
    67                         if (client.Connected == true)
    68                         {
    69                             service.AddItem(string.Format("与{0}失去联系,已停止接收该用户信息",
    70                                 client.Client.RemoteEndPoint));
    71                         }
    72                     }
    73                     //退出循环
    74                     break;
    75                 }
    76                 service.AddItem(string.Format("来自{0}:{1}", user.userName, receiveString));
    77                 string[] splitString = receiveString.Split(',');
    78                 string command = splitString[0].ToLower();
    79                 //获取当前传送的数据
    80                 switch (command)
    81                 {
    82                     default:
    83                         service.SendToAll(userList, "要发送的数据");
    84                         break;
    85                 }
    86             }
    87             userList.Remove(user);
    88             client.Close();
    89             service.AddItem(string.Format("有一个退出,剩余连接用户数:{0}", userList.Count));
    90         }
    View Code

      Service类:

    class Service
        {
            private ListBox listbox;
            private delegate void AddItemDelegate(string str);
            private AddItemDelegate addItemDelegate;
            public Service(ListBox listbox)
            {
                this.listbox = listbox;
                addItemDelegate = new AddItemDelegate(AddItem);
            }
    
            /// <summary>
            /// 在listbox中追加信息
            /// </summary>
            /// <param name="str">要追加的信息</param>
            public void AddItem(string str)
            {
                if (listbox.InvokeRequired)
                    listbox.Invoke(addItemDelegate, str);
                else
                {
                    listbox.Items.Add(str);
                    listbox.SelectedIndex = listbox.Items.Count - 1;
                    listbox.ClearSelected();
                }
            }
    
            /// <summary>
            /// 向某个客户端发送信息
            /// </summary>
            /// <param name="user">指定客户</param>
            /// <param name="str">信息</param>
            public void SendToOne(User user, string str)
            {
                try
                {
                    user.sw.WriteLine(str);
                    user.sw.Flush();
                    AddItem(string.Format("向{0}发送{1}", user.userName, str));
                }
                catch (Exception ex)
                {
                    AddItem(string.Format("向{0}发送消息失败,原因:{1}", user.userName, ex.Message));
                }
            }
    
    
            /// <summary>
            /// 向所有客户端发送信息
            /// </summary>
            /// <param name="userList">客户列表</param>
            /// <param name="str">信息</param>
            public void SendToAll(List<User> userList, string str)
            {
                for (int i = 0; i < userList.Count; i++)
                {
                    SendToOne(userList[i], str);
                }
            }
        }
    View Code

      客户机组(list)类:

     1  /// <summary>
     2     /// 客户机
     3     /// </summary>
     4     class User
     5     {
     6         public TcpClient client { get; set; }
     7         public StreamReader sr { get; private set; }
     8         public StreamWriter sw { get; private set; }
     9         public string userName { get; set; }
    10         public User(TcpClient client)
    11         {
    12             this.client = client;
    13             this.userName = "";
    14             NetworkStream netStream = client.GetStream();
    15             sr = new StreamReader(netStream, Encoding.UTF8);
    16             sw = new StreamWriter(netStream, Encoding.UTF8);
    17         }
    18     }
    View Code

      其实,现在呢,就是把整个客户机放到一个list里面,而listbox只是为了单纯的显示消息而已

      客户机原理:

     1         private TcpClient client = null;
     2         private StreamWriter sw;
     3         private StreamReader sr;
     4         private Service service;
     5         //是否正常退出接收线程
     6         private bool normalExit = false;
     7         
     8         /// <summary>
     9         /// 连接服务器
    10         /// </summary>
    11         private void GetService()
    12         {
    13             try
    14             {
    15                 client = new TcpClient();
    16                 //服务器IP
    17                 client.Connect(IPAddress.Parse(ConfigurationManager.AppSettings["IP"]), int.Parse(ConfigurationManager.AppSettings["Port"]));
    18                 //获取网络流
    19                 NetworkStream netStream = client.GetStream();
    20                 sr = new StreamReader(netStream, System.Text.Encoding.UTF8);
    21                 sw = new StreamWriter(netStream, System.Text.Encoding.UTF8);
    22                 //信息基本提示
    23                 service = new Service(listBox1, sw);
    24                 //给服务器消息
    25                 service.SendToServer("success");
    26                 //数据处理(服务器消息)
    27                 Thread threadReceive = new Thread(new ThreadStart(ReceiveData));
    28                 threadReceive.Start();
    29             }
    30             catch (Exception ex)
    31             {
    32                 MessageBox.Show("与服务器连接失败,原因:" + ex.Message, "提示",
    33                     MessageBoxButtons.OK, MessageBoxIcon.Information);
    34                 return;
    35             }
    36 
    37         }
    38         /// <summary>
    39         /// 接受服务器端的消息
    40         /// </summary>
    41         private void ReceiveData()
    42         {
    43             bool exitWhile = false;
    44             while (exitWhile == false)
    45             {
    46                 string receiveString = null;
    47                 try
    48                 {
    49                     receiveString = sr.ReadLine();
    50                 }
    51                 catch
    52                 {
    53                     service.AddItemToListBox("接收数据失败");
    54                 }
    55                 if (receiveString == null)
    56                 {
    57                     if (normalExit == false)
    58                     {
    59                         MessageBox.Show("与服务器失去联系!");
    60                     }
    61                     //结束线程
    62                     break;
    63                 }
    64                 service.AddItemToListBox("收到:" + receiveString);
    65                 string[] splitString = receiveString.Split(',');
    66                 string command = splitString[0].ToLower();
    67                 switch (command)
    68                 {
    69                     default:
    70                         GetControl(command);//这里的GetControl是一个处理值的方法,
    71                         this.Invalidate();
    72                         break;
    73                 }
    74             }
    75             Application.Exit();
    76         }
    View Code

      客户机Service类:

     1     class Service
     2     {
     3         ListBox listbox;
     4         StreamWriter sw;
     5         public Service(ListBox listbox, StreamWriter sw)
     6         {
     7             this.listbox = listbox;
     8             this.sw = sw;
     9         }
    10         /// <summary>向服务器发送数据</summary>
    11         public void SendToServer(string str)
    12         {
    13             try
    14             {
    15                 sw.WriteLine(str);
    16                 sw.Flush();
    17             }
    18             catch
    19             {
    20                 AddItemToListBox("发送数据失败");
    21             }
    22         }
    23         delegate void ListBoxDelegate(string str);
    24         /// <summary>在listbox中追加信息<</summary>
    25         /// <param name="str">要追加的信息</param>
    26         public void AddItemToListBox(string str)
    27         {
    28             try
    29             {
    30                 if (listbox.InvokeRequired)
    31                 {
    32                     ListBoxDelegate d = AddItemToListBox;
    33                     listbox.Invoke(d, str);
    34                 }
    35                 else
    36                 {
    37                     listbox.Items.Add(str);
    38                     listbox.SelectedIndex = listbox.Items.Count - 1;
    39                     listbox.ClearSelected();
    40                 }
    41             }
    42             catch
    43             {
    44 
    45             }
    46         }
    47     }
    View Code

      这就是一个完整的socket了,第一次做,肯定很多没有想到的地方,希望大神及时提出宝贵意见。

  • 相关阅读:
    MUI常用脚本及原生JavaScript常用操作元素方法
    cmf5分页相关
    TP5数据库操作方法总结
    mui的选项卡js选中指定项
    thinkphp 5数据库操作
    阻止touchslider事件冒泡,防止左右滑动时出发全局滑动事件
    thinkcmf5 学习笔记
    PHP Fatal error: Call to undefined function thinkfinfo_open()
    phpstudy iis版本 php4.4.5 和 php5.6.7目录权限问题
    手机uc不支持伪元素使用animation动画;移动端background-attachment:fixed不兼容性
  • 原文地址:https://www.cnblogs.com/JeffController/p/4398495.html
Copyright © 2020-2023  润新知