Tcp学习

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


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

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

view sourceprint?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前缀的就是服务器返回来的回应

  

show sourceview sourceprint?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,  

   

   

    }  

} 

  

  

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

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

  

show sourceview sourceprint?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; 

 

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

 

view sourceprint?    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;  

        }  

    } 
view sourceprint?  

posted @ 2011-03-31 22:36  eie  阅读(154)  评论(0)    收藏  举报