zoukankan      html  css  js  c++  java
  • C#.NET 比较好用的tcp通信模板(客户端篇)

    小弟最近在做毕业设计,搞的就是那模拟网吧管理的一个玩意儿系统。
    在客户端不进行数据库的操作,所以就需要tcp去通信来联系了。
    网上搜索的东西零零碎碎,也不齐全,小弟用了好久终于整理好的一套齐全的TCP通信模板,忍不住想贴出来共享共享咯。


    这里先讲客户端,下一篇就讲服务器端咯。

    下面这个类的对象就是在通信过程中发送的东西。
    因为对网上发送字符串,用分号隔开的做法感到很不爽。发送对象就方便操作多了。(类里面的东西太多了,都发送过去的话...无限YY中哇)
    其实也就是在发送的时候进行序列化,接收的时候进行反序列化。

    namespace commands
    {
    //注意这行,序列化用的
        [Serializable]
        public class MessageInfo
        {
            public commands.CommandsTypes CommandsTypes { get; set; }
            public string MessageContent { get; set; }
    
            public string NameForm { get; set; }
            public string Password { get; set; }
            public string  NameTo { get; set; }
    
    
    
        }
    }

     

     

    下面就是我那CommandsTypes 的枚举。
    Request前缀就是对服务器发送的请求,Res前缀的就是服务器返回来的回应

      

    namespace commands
    {
        public  enum CommandsTypes
        {
            /// <summary>
            /// 机器连接
            /// </summary>
            RequestMachineLogin,
    
    
            ResMachineLogin,
            RequestLogout,
    
            /// <summary>
            /// 发送信息给别人
            /// </summary>
            RequestTalk,
    
            /// <summary>
            /// 修改密码
            /// </summary>
            RequestModPWD,
    
            /// <summary>
            /// 修改密码
            /// </summary>
            ResModPWD,
    
            /// <summary>
            /// 用户登录
            /// </summary>
            RequestUserLogin,
    
            /// <summary>
            /// 用户登陆
            /// </summary>
            ResUserLogin,
    
            /// <summary>
            /// 用户登出
            /// </summary>
            RequestUserlogout,
    
            /// <summary>
            /// 用户登出
            /// </summary>
            ResUserlogout,
    
            /// <summary>
            ///用了多久
            /// </summary>
            RequestHowLong,
    
            /// <summary>
            ///用了多久
            /// </summary>
            ResHowLong,
    
            /// <summary>
            /// 换机子
            /// </summary>
            RequestChangeComputer,
    
            /// <summary>
            /// 换机子
            /// </summary>
            ResChangeComputer,
    
    
        }
    }
    

      

      

    有了这两个,就可以进入正题鸟哇。

    这是我添加的引用,至于哪个空间干嘛的大家就自个去捋顺吧

      

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.Remoting;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    using System.Diagnostics;
    using System.Configuration;
    using commands;

     

    下面就是主题鸟,通信的东西全在里面

     

            IPAddress localAddress;
            private bool isExit = false;
            private TcpClient client;
            private BinaryReader br;
            private BinaryWriter bw;
            //是否已经连接服务器,用于用户登录
            private bool isMechineLogined=false;
    
            private static string clientUserName;       
            /// <summary>
            /// 发送消息的一个例子:用户登录,在服务器验证账号密码,我那项目里面还有很多,放出来浪费大家时间了
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btn_OK_Click(object sender, EventArgs e)
            {
                if (isMechineLogined)
                {
                    MessageInfo obj_login = new MessageInfo();
    
                    obj_login.CommandsTypes = CommandsTypes.RequestUserLogin;
                    obj_login.NameForm = UsernameTextBox.Text;
                    obj_login.Password = PasswordTextBox.Text;
                    SendMessage(obj_login);
                }
                else
                {
                    MessageBox.Show("服务器连接失败!");
                    if (!isMechineLogined)
                    {
                        ConnectServer();
                    } 
                }
    
            }
    
            private void FrmLogin_Load(object sender, EventArgs e)
            {
                if (!isMechineLogined)
                {
                    ConnectServer();
                }
            }
    
            /// <summary>
            /// 连接服务器
            /// </summary>
            public void ConnectServer()
            {
                //buttonConnect.Enabled = false;
                try
                {
                    //服务器ip,这里暂时放在配置文件里面
                    string ipaddress = System.Configuration.ConfigurationManager.AppSettings["IPAddress"];
                    client = new TcpClient(ipaddress, 51888);
                    label_connectStatus.Text = "已连接服务器";
                    isMechineLogined = true;
    
    
                }
                catch (Exception)
                {
                    label_connectStatus.Text = "连接失败";
                    isMechineLogined = false;
                    return;
    
                }
    		//这个方法到这里为止,连接就完成了,下面的就和收消息与发消息有关了
                NetworkStream networkstream = client.GetStream();
                br = new BinaryReader(networkstream);
                bw = new BinaryWriter(networkstream);
    
    
                MessageInfo userSend = new MessageInfo();
                userSend.CommandsTypes = CommandsTypes.RequestMachineLogin;
                SendMessage(userSend);
    
    		//创建收消息的线程
                Thread threadRecive = new Thread(new ThreadStart(ReceiveData));
                threadRecive.IsBackground = true;
                threadRecive.Start();
    
    
            }
    
            /// <summary>
            /// 处理从服务器收到的信息
            /// </summary>
            private void ReceiveData()
            {
    
                MessageInfo pc;
                while (isExit == false)
                {
                    try
                    {
    			//使用缓冲
                        byte[] bytes = new byte[999];
                        int i = br.Read(bytes, 0, 999);
                        MemoryStream memory = new MemoryStream(bytes);
                        BinaryFormatter format = new BinaryFormatter();
                        pc = (MessageInfo)format.Deserialize(memory);
    
                    }
                    catch (Exception)
                    {
                        if (isExit == false)
                        {
                            MessageBox.Show("网络连接中断!");
                            isMechineLogined = false;
    
                            ShowMain();
    
                        }
                        break;
                    }
    		//处理从服务器收到的信息
                    switch (pc.CommandsTypes)
                    {
                        case CommandsTypes.ResUserLogin:
    			//规定服务器那边验证账号密码成功就把MessageContent=="true",否则就是失败原因
                            if (pc.MessageContent=="true")
                            {
                                //登录成功
                                //MessageBox.Show("登录成功");
     				HideMain();
                                clientUserName= pc.NameTo;
                            }
                            else 
                            {
                                //登录失败
                                MessageBox.Show("登录失败:"+pc.MessageContent);
                            }
    
                            break;
                        case CommandsTypes.ResHowLong:
                            MessageBox.Show(pc.MessageContent);
                            break;
                        case CommandsTypes.ResUserlogout:
                            if (pc.MessageContent == "true")
                            {
                                //下机成功
            		    ShowMain();
                                //MessageBox.Show("下机成功");
                        
                            }
                            else
                            {
                                //下机失败
                                MessageBox.Show("下机失败");
                            }
                            break;
                        case CommandsTypes.RequestTalk:
                            MessageBox.Show(pc.MessageContent);
                            break;
    
                        case CommandsTypes.ResModPWD:
                            MessageBox.Show(pc.MessageContent);
                            break;
                        default:
                            break;
                    }
    
                }
    
            }
    
            /// <summary>
            /// 向服务器发送信息
            /// </summary>
            /// <param name="message"></param>
            private void SendMessage(MessageInfo sendObject)
            {
    
                MemoryStream memory = new MemoryStream();
                BinaryFormatter format = new BinaryFormatter();
                format.Serialize(memory, sendObject);
                byte[] bytes = memory.ToArray();
                try
                {
                    bw.Write(bytes);
                    bw.Flush();
                }
                catch (Exception)
                {
                    //MessageBox.Show("发送失败!");
                }
            }
    
    
    
            /// <summary>
            /// 线程委托,这里面有一个递归
    	///我用来隐藏主界面和显示系统托盘的图标的
            /// </summary>
            /// <param name="str"></param>
            private delegate void HideMainDelegate();
            private void HideMain()
            {
                //子线程调用
                if (this.InvokeRequired)
                {
                    HideMainDelegate d = HideMain;
                    this.Invoke(d);
    
                }
                //创建控件的父线程调用
                else
                {
                    notifyIcon_Main.Visible = true;
                    this.Visible = false;
                }
            }
            private delegate void ShowMainDelegate();
            private void ShowMain()
            {
                //子线程调用
                if (this.InvokeRequired)
                {
                    ShowMainDelegate d = ShowMain;
                    this.Invoke(d);
    
                }
                //父线程调用
                else
                {
                    kboardhook.KeyMaskStart();
                    notifyIcon_Main.Visible = false;
                    this.Visible = true;
                }
            }
    
    

    好鸟,客户端一些主要的方法就放出来鸟。
    敬请期待下一篇博文,服务器端篇。
    ps转载请注明出处谢谢

  • 相关阅读:
    【入门OJ】2003: [Noip模拟题]寻找羔羊
    vue history模式 ios微信分享坑
    JS预解释
    vuex存储和本地存储(localstorage、sessionstorage)的区别
    call、apply、bind
    正则表达式常用元字符
    微信公众号自定义菜单跳转到相关联小程序
    javaScript运动框架之缓冲运动
    javaScript运动框架之匀速运动
    js事件冒泡、阻止事件冒泡以及阻止默认行为
  • 原文地址:https://www.cnblogs.com/salty/p/2001423.html
Copyright © 2011-2022 走看看