小弟最近在做毕业设计,搞的就是那模拟网吧管理的一个玩意儿系统。
在客户端不进行数据库的操作,所以就需要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转载请注明出处谢谢

posted on 2011-03-31 19:34  绍体  阅读(4020)  评论(1编辑  收藏  举报