zoukankan      html  css  js  c++  java
  • 将之前的通信代码,以winform界面的形式写出来

    winform应用程序,与控制台程序的代码没有太大的区别,最大的不同是将代码拆分成一个个小块,即一个个的方法,这样可以通过一个个的控件(按钮button等)去触发事件(方法)。 但是我感觉,不好的是,winform程序容易因为点击按钮的顺序,次数的不同,使程序出错,所以要多多的用try-catch。

    客户端代码

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Windows.Forms;
      9 using System.Net;
     10 using System.Net.Sockets;
     11 using System.Threading;
     12 
     13 namespace WindowsForms_客户端
     14 {
     15     public partial class Form1 : Form
     16     {
     17 
     18         byte[] data;
     19         string stringData;
     20         //创建服务器端IPEndPoint对象
     21         IPEndPoint Ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 125);
     22         Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     23 
     24         public Form1()
     25         {
     26             InitializeComponent();
     27         }
     28 
     29         /// <summary>
     30         /// 与服务器建立连接
     31         /// </summary>
     32         /// <param name="sender"></param>
     33         /// <param name="e"></param>
     34         private void buttonConnect_Click(object sender, EventArgs e)
     35         {
     36             try
     37             {
     38                 server.Connect(Ipep);
     39                 textState.AppendText("连接成功
    ");
     40             }
     41             catch
     42             {
     43                 textState.AppendText("连接服务器失败
    ");
     44                 MessageBox.Show("请先启动服务器,再启动客户端");
     45                 return;
     46             }
     47             Thread th = new Thread(Receive);
     48             th.IsBackground = true;
     49             th.Start();
     50         }
     51 
     52         /// <summary>
     53         /// 断开与服务器的连接
     54         /// </summary>
     55         /// <param name="sender"></param>
     56         /// <param name="e"></param>
     57         private void buttonBreak_Click(object sender, EventArgs e)
     58         {
     59             server.Shutdown(SocketShutdown.Both);
     60             server.Close();
     61             textState.AppendText("断开与服务器的连接
    ");
     62         }
     63 
     64         
     65 
     66         /// <summary>
     67         /// 接收消息的方法  用的方法是ReceiveVarMessage 接收变长消息
     68         /// </summary>
     69         void Receive()
     70         {
     71             while (true)
     72             {
     73                 data = ReceiveVarMessage(server);
     74                 if (data.Length == 0)
     75                 {
     76                     break;
     77                 }
     78                 stringData = Encoding.UTF8.GetString(data, 0, data.Length);
     79                 textReceive.AppendText(stringData + "
    ");
     80             }
     81 
     82 
     83             //while (true)
     84             //{
     85             //    //接收数据
     86             //    int receive = server.Receive(data);//receive是接收到的数据的长度 所以是int型  接收到的信息,存在data这个byte字节数组中
     87             //    if (receive == 0)
     88             //    {
     89             //        break;
     90             //    }
     91             //    stringData = Encoding.UTF8.GetString(data, 0, receive);
     92             //    textReceive.AppendText(stringData + "
    ");
     93             //}
     94         }
     95 
     96         /// <summary>
     97         /// 跨线程访问
     98         /// </summary>
     99         /// <param name="sender"></param>
    100         /// <param name="e"></param>
    101         private void Form1_Load(object sender, EventArgs e)
    102         {
    103             Control.CheckForIllegalCrossThreadCalls = false;
    104             textKp.Text = "0.4";
    105             textKi.Text = "0.53";
    106             textKd.Text = "0.1";
    107             textKd.Focus();
    108 
    109         }
    110 
    111         /// <summary>
    112         /// 发送消息到服务器端
    113         /// </summary>
    114         /// <param name="sender"></param>
    115         /// <param name="e"></param>
    116         private void buttonSend_Click(object sender, EventArgs e)
    117         {
    118             string str = textSend.Text;
    119             data = System.Text.Encoding.UTF8.GetBytes(str);
    120             SendVarMessage(server, data);
    121         }
    122 
    123         private void textReceive_TextChanged(object sender, EventArgs e)
    124         {
    125 
    126         }
    127 
    128         int i = 0;
    129         /// <summary>
    130         /// 客户端发送设定速度值 给服务器端
    131         /// </summary>
    132         /// <param name="sender"></param>
    133         /// <param name="e"></param>
    134         private void button1_Click(object sender, EventArgs e)
    135         {
    136             string speed = textSetspeed.Text;
    137             try
    138             {
    139                 double dSpeed = Convert.ToDouble(speed);
    140                 data = System.Text.Encoding.UTF8.GetBytes(speed);
    141                 textSend.AppendText(""+(i+1)+"次发送的设定速度值是"+speed+"
    ");
    142                 SendVarMessage(server, data);
    143                 //server.Send(data);
    144                 i++;
    145                 textSetspeed.Clear();
    146                 textSetspeed.Focus();
    147             }
    148             catch
    149             {
    150                 MessageBox.Show("输入速度设定值不正确,请重新输入");
    151                 textSend.AppendText(speed + "
    ");
    152                 textSetspeed.Clear();
    153                 textSetspeed.Focus();
    154             }
    155         }
    156 
    157         /// <summary>
    158         /// 发送变长消息方法
    159         /// </summary>
    160         /// <param name="s"></param>
    161         /// <param name="msg"></param>
    162         /// <returns></returns>
    163         private static void SendVarMessage(Socket s, byte[] msg)
    164         {
    165             int offset = 0;
    166             int sent;
    167             int size = msg.Length;
    168             int dataleft = size;
    169             byte[] msgsize = new byte[2];
    170 
    171             //将消息的尺寸从整型转换成可以发送的字节型
    172             //因为int型是占4个字节 所以msgsize是4个字节 后边是空字节
    173             msgsize = BitConverter.GetBytes(size);
    174 
    175             //发送消息的长度信息
    176             //之前总是乱码出错 客户端接收到的欢迎消息前两个字节是空 后边的两个字符er传送到第二次接收的字节数组中
    177             //因此将er字符转换为int出错  这是因为之前在Send代码中,是将msgsize整个字节数组发送给客户端 所以导致第3 4个空格也发送
    178             //导致发送的信息混乱 这两个空格使发送的信息都往后挪了两个位置  从而乱码
    179             sent = s.Send(msgsize, 0, 2, SocketFlags.None);
    180             while (dataleft > 0)
    181             {
    182                 int sent2 = s.Send(msg, offset, dataleft, SocketFlags.None);
    183                 //设置偏移量
    184                 offset += sent2;
    185                 dataleft -= sent2;
    186             }
    187         }
    188 
    189         /// <summary>
    190         /// 接收变长消息方法
    191         /// </summary>
    192         /// <param name="s"></param>
    193         /// <returns>接收到的信息</returns>
    194         private static byte[] ReceiveVarMessage(Socket s)//方法的返回值是字节数组 byte[] 存放的是接受到的信息
    195         {
    196             int offset = 0;
    197             int recv;
    198             byte[] msgsize = new byte[2];
    199 
    200             //接收2个字节大小的长度信息
    201             recv = s.Receive(msgsize, 0, 2, 0);
    202 
    203             //将字节数组的消息长度转换为整型
    204             int size = BitConverter.ToInt16(msgsize, 0);
    205             int dataleft = size;
    206             byte[] msg = new byte[size];
    207             while (dataleft > 0)
    208             {
    209                 //接收数据
    210                 recv = s.Receive(msg, offset, dataleft, 0);
    211                 if (recv == 0)
    212                 {
    213                     break;
    214                 }
    215                 offset += recv;
    216                 dataleft -= recv;
    217             }
    218             return msg;
    219         }
    220 
    221         ///// <summary>
    222         ///// 将kp参数的设置,发送给客户端     这里还没有客户端在线修改kp ki kd参数的功能 
    223         ///// </summary>
    224         ///// <param name="sender"></param>
    225         ///// <param name="e"></param>
    226         private void buttonChange_Click(object sender, EventArgs e)
    227         {
    228         //    data = System.Text.Encoding.UTF8.GetBytes(textKp.Text);
    229         //    SendVarMessage(server, data);
    230 
    231         //    //data = System.Text.Encoding.UTF8.GetBytes(textKi.Text);
    232         //    //SendVarMessage(server, data);
    233 
    234         //    //data = System.Text.Encoding.UTF8.GetBytes(textKd.Text);
    235         //    //SendVarMessage(server, data);
    236         }
    237 
    238         ///// <summary>
    239         ///// 修改ki参数
    240         ///// </summary>
    241         ///// <param name="sender"></param>
    242         ///// <param name="e"></param>
    243         private void buttonChangeki_Click(object sender, EventArgs e)
    244         {
    245         //    data = System.Text.Encoding.UTF8.GetBytes(textKi.Text);
    246         //    SendVarMessage(server, data);
    247         }
    248 
    249         ///// <summary>
    250         ///// 修改kd参数
    251         ///// </summary>
    252         ///// <param name="sender"></param>
    253         ///// <param name="e"></param>
    254         private void buttonChangekd_Click(object sender, EventArgs e)
    255         {
    256         //    data = System.Text.Encoding.UTF8.GetBytes(textKd.Text);
    257         //    SendVarMessage(server, data);
    258         }
    259 
    260 
    261     }
    262 }

    服务器端代码:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Windows.Forms;
      9 using System.Net;
     10 using System.Net.Sockets;
     11 using System.Threading;
     12 using System.Collections;
     13 
     14 namespace WindowsForms_服务器端
     15 {
     16     public partial class Form1 : Form
     17     {
     18         public Form1()
     19         {
     20             InitializeComponent();
     21         }
     22         double[] nums = new double[3];//存储3个偏差值e(k) e(k-1) e(k-2)
     23         double actual = 0;
     24         double set = 0;
     25         double kp;
     26         double ki;
     27         double kd;
     28         //定义一个空字节数组date作为数据缓冲区,用于缓冲流入和流出的信息
     29         byte[] date;
     30         static Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     31         static Socket client;
     32         ArrayList list = new ArrayList();//存储客户端发来的速度设定值
     33         ArrayList listOut = new ArrayList();//存储PID计算的实际速度值
     34         Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();//创建键值对,存储套接字的ip地址等信息
     35 
     36         Thread thConnect;
     37 
     38         /// <summary>
     39         /// 建立与客户端的连接
     40         /// </summary>
     41         /// <param name="sender"></param>
     42         /// <param name="e"></param>
     43         private void buttonConnect_Click(object sender, EventArgs e)
     44         {
     45             try
     46             {
     47                 IPEndPoint Ipep = new IPEndPoint(IPAddress.Any, 125);//指定地址和端口号
     48                 newsock.Bind(Ipep);
     49                 newsock.Listen(10);//置于监听状态
     50                 textState.Text = "等待客户端的连接
    ";
     51                 thConnect = new Thread(Connect);
     52                 thConnect.IsBackground = true;
     53                 thConnect.Start();
     54                 //Receive();
     55             }
     56             catch
     57             { }
     58         }
     59 
     60         /// <summary>
     61         /// 不断接收从客户端发来消息的方法
     62         /// </summary>
     63         void Receive()
     64         {
     65             try
     66             {
     67                 while (true)
     68                 {
     69                     date = ReceiveVarMessage(client);
     70                     if (date.Length == 0)
     71                     {
     72                         break;
     73                     }
     74                     string str = Encoding.UTF8.GetString(date, 0, date.Length);
     75                     list.Add(str);
     76                     textReceive.AppendText(str + "
    ");
     77                 }
     78             }
     79             catch
     80             { }
     81         }
     82 
     83         /// <summary>
     84         /// 服务器端与客户端连接的方法  使一个服务器可以与多个客户端连接
     85         /// </summary>
     86         private void Connect()
     87         {
     88             //接收来自客户端的接入尝试连接,并返回连接客户端的ip地址
     89             while (true)
     90             {
     91                 client = newsock.Accept();
     92                 IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
     93                 //返回客户端的ip地址和端口号
     94                 textState.AppendText("" + clientep.Address + "" + clientep.Port + "端口连接
    ");
     95                 dicSocket.Add(clientep.ToString(), client);//将连接的客户端的IP地址添加在键值对集合中
     96                 comboBox.Items.Add(clientep);//将客户端的IP地址显示在下拉栏中
     97                 //Receive();
     98                 Thread thReceive = new Thread(Receive);//创建一个新线程 执行Receive()方法
     99                 thReceive.IsBackground = true;
    100                 thReceive.Start();
    101             }
    102         }
    103 
    104         /// <summary>
    105         /// 发送消息给客户端 需自己选择已连接的其中一个客户端
    106         /// </summary>
    107         /// <param name="sender"></param>
    108         /// <param name="e"></param>
    109         private void buttonSend_Click(object sender, EventArgs e)
    110         {
    111             try
    112             {
    113                 string str = textSend.Text;
    114                 date = System.Text.Encoding.UTF8.GetBytes(str); //以字节数组的形式 将欢迎信息发送给客户端 注意发送与接收要用相同的编码格式UTF8 否则会乱码
    115                 try
    116                 {
    117                     string ip = comboBox.SelectedItem.ToString();
    118                     SendVarMessage(dicSocket[ip], date);
    119                 }
    120                 catch
    121                 {
    122                     MessageBox.Show("发送失败,请确认已选择一个客户端");
    123                 }
    124             }
    125             catch
    126             { }
    127         }
    128 
    129 
    130         /// <summary>
    131         /// 断开与客户端的连接
    132         /// </summary>
    133         /// <param name="sender"></param>
    134         /// <param name="e"></param>
    135         private void buttonBreak_Click(object sender, EventArgs e)
    136         {
    137             try
    138             {
    139                 client.Close();
    140                 newsock.Close();
    141                 textState.AppendText("断开连接
    ");
    142             }
    143             catch { }
    144         }
    145 
    146         /// <summary>
    147         /// 跨线程访问
    148         /// </summary>
    149         /// <param name="sender"></param>
    150         /// <param name="e"></param>
    151         private void Form1_Load(object sender, EventArgs e)
    152         {
    153             Control.CheckForIllegalCrossThreadCalls = false;
    154         }
    155 
    156         private void textState_TextChanged(object sender, EventArgs e)
    157         {
    158 
    159         }
    160 
    161         private void textReceive_TextChanged(object sender, EventArgs e)
    162         {
    163 
    164         }
    165 
    166         /// <summary>
    167         /// 开始进行PID计算
    168         /// </summary>
    169         /// <param name="sender"></param>
    170         /// <param name="e"></param>
    171         private void button1_Click(object sender, EventArgs e)
    172         {
    173             //Thread thKp = new Thread(GetKp);
    174             //thKp.IsBackground = true;
    175             //thKp.Start();
    176             ////date=ReceiveVarMessage(client);
    177             ////string strKp = Encoding.UTF8.GetString(date,0,date.Length);
    178             ////kp = Convert.ToDouble(strKp);
    179 
    180             //Thread thKi = new Thread(GetKi);
    181             //thKi.IsBackground = true;
    182             //thKi.Start();
    183             ////date = ReceiveVarMessage(client);
    184             ////string strKi = Encoding.UTF8.GetString(date, 0, date.Length);
    185             ////ki = Convert.ToDouble(strKi);
    186 
    187             //Thread thKd = new Thread(GetKd);
    188             //thKd.IsBackground = true;
    189             //thKd.Start();
    190             ////date = ReceiveVarMessage(client);
    191             ////string strKd = Encoding.UTF8.GetString(date);
    192             ////kd = Convert.ToDouble(strKd);
    193 
    194             int n = list.Count;
    195             int i = 0;
    196             while (i < n)
    197             {
    198                 set = double.Parse(list[i].ToString());
    199                 nums[0] = set - actual;
    200                 double increase = 0.4* (nums[0] - nums[1]) + 0.53 * nums[0] + 0.1 * (nums[0] - 2 * nums[1] + nums[2]);
    201                 actual += increase;
    202                 listOut.Add(actual);//将每次的实际速度值  添加到集合中
    203                 textActualspeed.AppendText("" + (i + 1) + "次的实际输出速度是" + actual + "
    "); //输出实际的速度值 成功!
    204                 nums[1] = nums[0];
    205                 nums[2] = nums[1];
    206                 i++;
    207             }
    208         }
    209 
    210         ///// <summary>
    211         ///// 得到客户端传来的Kp参数
    212         ///// </summary>
    213         //private void GetKp()
    214         //{
    215         //    date = ReceiveVarMessage(client);
    216         //    string strKp = Encoding.UTF8.GetString(date, 0, date.Length);
    217         //    kp = Convert.ToDouble(strKp);
    218         //}
    219 
    220         ///// <summary>
    221         ///// 得到客户端传来的Ki参数
    222         ///// </summary>
    223         //private void GetKi()
    224         //{
    225         //    date = ReceiveVarMessage(client);
    226         //    string strKi = Encoding.UTF8.GetString(date, 0, date.Length);
    227         //    ki = Convert.ToDouble(strKi);
    228         //}
    229 
    230         ///// <summary>
    231         ///// 得到客户端传来的Kd参数
    232         ///// </summary>
    233         //private void GetKd()
    234         //{
    235         //    date = ReceiveVarMessage(client);
    236         //    string strKd = Encoding.UTF8.GetString(date, 0, date.Length);
    237         //    kd = Convert.ToDouble(strKd);
    238         //}
    239 
    240         /// <summary>
    241         /// 发送变长消息方法
    242         /// </summary>
    243         /// <param name="s"></param>
    244         /// <param name="msg"></param>
    245         /// <returns></returns>
    246         private static void SendVarMessage(Socket s, byte[] msg)
    247         {
    248             int offset = 0;
    249             int sent;
    250             int size = msg.Length;
    251             int dataleft = size;
    252             byte[] msgsize = new byte[2];
    253 
    254             //将消息的尺寸从整型转换成可以发送的字节型
    255             //因为int型是占4个字节 所以msgsize是4个字节 后边是空字节
    256             msgsize = BitConverter.GetBytes(size);
    257 
    258             //发送消息的长度信息
    259             //之前总是乱码出错 客户端接收到的欢迎消息前两个字节是空 后边的两个字符er传送到第二次接收的字节数组中
    260             //因此将er字符转换为int出错  这是因为之前在Send代码中,是将msgsize整个字节数组发送给客户端 所以导致第3 4个空格也发送
    261             //导致发送的信息混乱 这两个空格使发送的信息都往后挪了两个位置  从而乱码
    262             sent = s.Send(msgsize, 0, 2, SocketFlags.None);
    263             while (dataleft > 0)
    264             {
    265                 int sent2 = s.Send(msg, offset, dataleft, SocketFlags.None);
    266                 //设置偏移量
    267                 offset += sent2;
    268                 dataleft -= sent2;
    269             }
    270             //return dataleft;
    271         }
    272 
    273         /// <summary>
    274         /// 接收变长消息方法
    275         /// </summary>
    276         /// <param name="s"></param>
    277         /// <returns>接收到的信息</returns>
    278         private static byte[] ReceiveVarMessage(object o)//方法的返回值是字节数组 byte[] 存放的是接受到的信息
    279         {
    280             Socket s = o as Socket;
    281             int offset = 0;
    282             int recv;
    283             byte[] msgsize = new byte[2];
    284 
    285             //接收2个字节大小的长度信息
    286             recv = s.Receive(msgsize, 0, 2, 0);
    287 
    288             //将字节数组的消息长度转换为整型
    289             int size = BitConverter.ToInt16(msgsize, 0);
    290             int dataleft = size;
    291             byte[] msg = new byte[size];
    292             while (dataleft > 0)
    293             {
    294                 //接收数据
    295                 recv = s.Receive(msg, offset, dataleft, 0);
    296                 if (recv == 0)
    297                 {
    298                     break;
    299                 }
    300                 offset += recv;
    301                 dataleft -= recv;
    302             }
    303             return msg;
    304         }
    305     }
    306 }

    这里还没有实现客户端在线修改kp ki kd参数的功能,pid计算用的参数是初始给定的定值。

    接收消息Receive部分的代码,是不断的接收对方发送来的消息,不能分辨其发送的是kp ki参数的设定值(double型),还是速度设定值setSpeed(int或double型),还是欢迎消息welcome to the server(string型),所以,应该需要标记符,放在要发送的消息中,如:字节数组第一位是0,表示发送的是速度设定值,第一位为2表示kp参数设定值……

  • 相关阅读:
    Insertion Sort List
    Same Tree
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    ZigZag Conversion
    Reverse Integer
    String to Integer (atoi)
    Palindrome Number
    eclipse 导入tortoiseSVN检出项目,不显示svn信息(eclipse安装svn插件)
    exception ORA-00918: 未明确定义列
  • 原文地址:https://www.cnblogs.com/1987-05-04/p/6692570.html
Copyright © 2011-2022 走看看