Socket编程实例

作者: fangaoxin
发布时间:2015-06-11 19:31:17

1.       无废话,先上图

     

 

2. 协议文档

 

1 协议概述

协议说明

       通过本协议可以实现Client与Server之间的消息传递

 

1.2 连接方式

l  Socket连接方式

以TCP/IP协议建立一个长连接, Server 监听IP和Port

 

1.3 术语表

       ClientMsg    Client=>Server 消息

       ServerMsg    Server=>Client 消息

       Server           代表服务器

       Client           代表客户端

       IP                 ServerIP地址

       Port                     端口

 

2 消息包的定义—Socket连接

 

2.1 基本格式

消息包由消息头和消息体共同组成。

项目

说明

消息头

消息头部分

消息体

消息体部分

 

 

 

 

 

 

 

 

消息中利用到如下数据类型

类型

说明

Integer

无符号整数

Text

定长字符串,左对齐存储,空余位置补’\0’

 

 

 



消息头的格式

字段

长度(字节)

类型

说明

Message Length

4

Integer

消息包总长度(字节)

Command ID

4

Integer

命令ID

Sequence ID

4

Integer

序列号

 

 






2.5 Client Msg 操作

命令方向:Client => Server

命令说明:用于向Server发送消息内容

               Client 产生 CLIENT_MSG 消息包

               Server 接收到后,返回CLIENT_MSG_RESP 消息包


CLIENT_MSG 命令的语法

字段

长度(字节)

类型

说明

ID

4

Integer

消息ID

Name

50

Text

物品名称

Class

30

Text

物品分类

Quantity

4

Integer

数量

Location

30

Text

存放地点

Reserve

8

Text

保留


CLIENT_MS_RESP应答的语法

字段

长度(字节)

类型

说明

Result

1

Integer

执行命令是否成功。

0 =执行成功

其它:执行错误

Reserve

8

Text

保留

 

 

2.6 Server Msg 操作

命令方向:Server => Client

命令说明:用于Server发送信息到 Client

                Server 产生 SERVER_MSG 消息包

                Client 接收到后,返回SERVER_MSG_RESP 消息包

SERVER_MSG 命令的语法

字段

长度(字节)

类型

说明

ID

4

Integer

消息ID

 

 

 

 

Reserve

8

Text

保留

SERVER_MSG_RESP应答的语法

字段

长度(字节)

类型

说明

Result

1

Integer

执行命令是否成功。

0:成功

其它:错误

Reserve

8

Text

保留

 

 

 

消息ID定义

消息ID名称

消息ID取值

BIND

0x1

BIND_RESP

0x80000001

UNBIND

0x2

UNBIND_RESP

0x80000002

ACTIVE_TEST

0x3

ACTIVE_TEST_ RESP

0x80000003

CLIENT_MSG

0x10

CLIENT_MSG_RESP

0x80000010

SERVER_MSG

0x20

SERVER_MSG_RESP

0x80000020

 

版本更新说明

版本号

说明

V 1.0

建立接口协议

 

 

 

 

 

 

 

 




3.代码

  #region enum
            public enum DEMO_COMMAND_ID : uint
            {
                DEMO_BIND = 0x00000001,
                DEMO_BIND_RESP = 0x80000001,

                DEMO_TERMINATE = 0x00000002,  // 终止连接
                DEMO_TERMINATE_RESP = 0x80000002,  // 终止连接应答
                
                DEMO_ACTIVE_TEST = 0x00000003, //激活测试
                DEMO_ACTIVE_TEST_RESP = 0x80000003,

                DEMO_CLIENT_MSG = 0x000000010,   
                DEMO_CLIENT_MSG_RESP = 0x80000010,  

                DEMO_SERVER_MSG = 0x00000020,  
                DEMO_SERVER_MSG_RESP = 0x80000020
            }

            public enum DEMO_EVENT_TYPE
            {
                OnBind=0,
                OnBindResp=1,
                OnUnbind=2,
                OnUnbindResp=3,
                OnTest = 4,
                OnTestResp = 5,
                OnClosed=6,
                OnClientMsg=7,
                OnClientMsgResp=8,
                OnServerMsg=9,
                OnServerMsgResp=10
                
            }

            #endregion

 

 


   #region DEMO_CLIENT_MSG
            public class DEMO_CLIENT_MSG
            {
                DEMO_MSG_HEADER header;

                public ClientMsg clientMsg = new ClientMsg();          

                public DEMO_CLIENT_MSG(uint seq)
                {
                    header = new DEMO_MSG_HEADER(DEMO_COMMAND_ID.DEMO_CLIENT_MSG);
                    header.Seq_ID = seq;
                    
                }

                public DEMO_CLIENT_MSG(byte[] bs)
                {
                    int index = 12;
                    index = index + 4;
                    clientMsg.Name = Encoding.Default.GetString(bs, index, GetRealLen(bs,index));
                    index = index + 50;
                    clientMsg.Class = Encoding.Default.GetString(bs, index, GetRealLen(bs, index));
                    index = index + 30;
                    clientMsg.Quantity = BIConvert.Bytes2UInt(bs,index);
                    index = index + 4;
                    clientMsg.Location = Encoding.Default.GetString(bs, index, GetRealLen(bs, index));

                }

                public byte[] GetBytes() //返回字节数印象
                {
                    byte[] submitData = new byte[800];
                    int index = MSG.DEMO_MSG_HEADER.HeaderLength;
                    {
                        #region 进入填充包的过程
                        BIConvert.Int2Bytes(clientMsg.ID).CopyTo(submitData, index);
                        index = index + 4;

                        byte[] msg = Encoding.Default.GetBytes(clientMsg.Name);
                        msg.CopyTo(submitData, index);
                        index = index + 50;

                        msg = Encoding.Default.GetBytes(clientMsg.Class);
                        msg.CopyTo(submitData, index);
                        index = index + 30;


                        BIConvert.Int2Bytes(clientMsg.Quantity).CopyTo(submitData, index);
                        index = index + 4;

                        msg = Encoding.Default.GetBytes(clientMsg.Location);
                        msg.CopyTo(submitData, index);
                        index = index + 30;

                        index = index + 8;
                        #endregion
                    }

                    header.MSG_Length = (uint)index;
                    byte[] reVal = new byte[index];
                    header.GetBytes().CopyTo(reVal, 0);
                    for (int i = DEMO_MSG_HEADER.HeaderLength; i < reVal.Length; i++)
                    {
                        reVal[i] = submitData[i];
                    }

                    return (reVal);
                }

                private int GetRealLen(byte[] bts, int index)
                {
                    int i = index;
                    for (; i < bts.Length; i++)
                    {
                        if (bts[i] == 0)
                        {
                            break;
                        }
                    }
                    return i - index;
                }
            }
            public class DEMO_CLIENT_MSG_RESP
            {

                DEMO_MSG_HEADER header;
                int _Result=0;
                public int Result
                {
                    set
                    {
                        this._Result = value;
                    }
                    get
                    {
                        return(this._Result);
                    }
                }
                public DEMO_CLIENT_MSG_RESP(byte[] bs)
                {
                    this._Result = (int)bs[12+1]; 
                }
                             
                public DEMO_CLIENT_MSG_RESP(uint seq)
                {
                    header=new DEMO_MSG_HEADER(DEMO_COMMAND_ID.DEMO_CLIENT_MSG_RESP);
                    header.Seq_ID=seq;
                    header.MSG_Length=(uint)DEMO_MSG_HEADER.HeaderLength+1+8;
                }
                public byte[] GetBytes()
                {
                    byte[] reVal=new byte[DEMO_MSG_HEADER.HeaderLength+1+8];
                    int index=0;
                    header.GetBytes().CopyTo(reVal,index);
                    index+=12;
                    reVal[index++]=(byte)this._Result;
                    index+=8; //reserve
                    return(reVal);
                }
            }
            #endregion

            #region DEMO_SERVER_MSG
            public class DEMO_SERVER_MSG : AtomBase
            {

                DEMO_MSG_HEADER header; 

                public DEMO_SERVER_MSG(byte[] bs)
                {     
                           
                    
                }            
            }

            public class DEMO_SERVER_MSG_RESP
            {

                DEMO_MSG_HEADER header;
                int _result=0;
             
                public DEMO_SERVER_MSG_RESP(uint sequence)
                {
                    header = new DEMO_MSG_HEADER(DEMO_COMMAND_ID.DEMO_SERVER_MSG_RESP);
                    header.Seq_ID = sequence;
                    header.MSG_Length = (uint)DEMO_MSG_HEADER.HeaderLength + 10 + 4;

                }

                public int Result
                {
                    set
                    {
                        this._result = value;
                    }
                }
                
                public byte[] GetBytes()
                {
                    byte[] reVal = new byte[MSG.DEMO_MSG_HEADER.HeaderLength + 10 + 4];
                   
                    return (reVal);
                }

            }
            #endregion

 

 

 


 private void TimeCall(object stat)
            {
                log.Msg("TimeCall", DateTime.Now.ToString());
                if (this.Connected)
                {
                    this.Send_DEMO_COMMAND(DEMO.MSG.DEMO_COMMAND_ID.DEMO_ACTIVE_TEST);
                    this.CallEvent(DEMO.MSG.DEMO_EVENT_TYPE.OnTest, "Send Active_test");
                }
                else
                {
                    //socket is closed!
                }
            }

            private void CallEvent(MSG.DEMO_EVENT_TYPE event_type, object objValue)
            {
                if (this.onDEMOEvent != null)
                {
                    MSG.DEMOEventArgs DEMOevent = new DEMO.MSG.DEMOEventArgs();
                    DEMOevent.DEMO_Event_Type = event_type;
                    switch (event_type)
                    {
                        case MSG.DEMO_EVENT_TYPE.OnClientMsg:
                            DEMOevent.clientMsg = (MSG.ClientMsg)objValue;
                            break;
                        case MSG.DEMO_EVENT_TYPE.OnServerMsg:
                            DEMOevent.serverMsg = (MSG.ServerMsg)objValue;
                            break;
                        default:
                            DEMOevent.Msg = (string)objValue;
                            break;
                    }
                    DEMOevent.SocketIndex = this.Index;
                    this.onDEMOEvent(this, DEMOevent);
                }
            }

 

 


     #region Listen
        private Socket ListenSocket;
        private Thread ListenThread;
        private static int MAXSOCKET = 20;


        public static ManualResetEvent allDone = new ManualResetEvent(false);
        private CDEMO[] SocClient = new CDEMO[MAXSOCKET];




        public void StartListen()
        {
            ListenThread = new Thread(new ThreadStart(Start));
            ListenThread.Start();
        }
        public void Start()
        {
            int Port = Convert.ToInt32(ini.GetValue("ServerListen", "Port"));
            string IP = ini.GetValue("ServerListen", "IP");
            try
            {
                IPEndPoint ipLocalEndPoint;
               // IPAddress ipAddress = Dns.Resolve(IP).AddressList[0];
                ipLocalEndPoint = new IPEndPoint(IPAddress.Parse(IP), Port); //Listen at Port 999

                ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ListenSocket.Bind(ipLocalEndPoint);
                ListenSocket.Listen(200);
                statusBarPanel2.Text = IP + ":" + Port.ToString();
                while (true)
                {
                    allDone.Reset();
                    ListenSocket.BeginAccept(new AsyncCallback(AcceptCallback), ListenSocket);
                    allDone.WaitOne();
                }

            }
            catch (Exception err)
            {
                log.Msg("Err_Listen", err.ToString()); ;
            }
        }

        public void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                allDone.Set();
                Socket listener = (Socket)ar.AsyncState;
                int i = this.GetAvailbleSocket();
                if ((i > -1) && (i < MAXSOCKET))
                {
                    InitSocket(ref SocClient[i], i);

                    SocClient[i].socket = listener.EndAccept(ar);
                    SocClient[i].onDEMOEvent += new CDEMO.DEMOEventHandler(Form1_onDEMOEvent);
                    SocClient[i].StartServer();
                }
            }
            catch (Exception err)
            {
                log.Msg("ERR_AcceptCallBack", err.ToString());
            }
        }

        void Form1_onDEMOEvent(object sender, Atomsoft.CSocket.DEMO.MSG.DEMOEventArgs e)
        {
            switch (e.DEMO_Event_Type)
            {
                case Atomsoft.CSocket.DEMO.MSG.DEMO_EVENT_TYPE.OnClientMsg:
                    elv.AddMsg(new string[] { e.clientMsg.Name, e.clientMsg.Class, e.clientMsg.Quantity.ToString(), e.clientMsg.Location });
                    db.SaveMsg(e.clientMsg);
                    break;
            }
        }

        private void InitSocket(ref CDEMO Soc, int nSocRef)
        {
            try
            {
                Soc = new CDEMO(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                Soc.SocketID = nSocRef;               
            }
            catch (Exception err)
            {
                log.Msg("ERR_InitSocket", err.ToString());
            }
        }

   
               
        private int GetAvailbleSocket()
        {
            int i = -1;
            for (i = 0; i < MAXSOCKET; i++)
            {
                try
                {
                    if (SocClient[i] == null)
                        break;

                    else
                    {
                        if (!SocClient[i].socket.Connected)
                        {

                            SocClient[i] = null;
                            break;
                        }
                    }
                }
                catch (Exception err)
                {
                    log.Msg("ERR_GetAvailbleSocket", err.ToString());
                }

            }          
            return i;
        }

        #endregion

 

 


private void Send_DEMO_COMMAND_RESP(MSG.DEMO_COMMAND_ID cmdID, uint seqid)
            {
                switch (cmdID)
                {
                    case MSG.DEMO_COMMAND_ID.DEMO_ACTIVE_TEST:
                        MSG.DEMO_MSG_TEST_RESP active_test_resp = new MSG.DEMO_MSG_TEST_RESP(seqid);
                        this.SendBytes(active_test_resp.GetBytes());
                        break;

                    case MSG.DEMO_COMMAND_ID.DEMO_TERMINATE:
                        MSG.DEMO_MSG_TERMINATE_RESP terminate_resp = new MSG.DEMO_MSG_TERMINATE_RESP(seqid);
                        this.SendBytes(terminate_resp.GetBytes());
                        break;
                    case MSG.DEMO_COMMAND_ID.DEMO_CLIENT_MSG:
                        MSG.DEMO_CLIENT_MSG_RESP clientMsg_resp = new Atomsoft.CSocket.DEMO.MSG.DEMO_CLIENT_MSG_RESP(seqid);
                        this.SendBytes(clientMsg_resp.GetBytes());
                        break;
                    case MSG.DEMO_COMMAND_ID.DEMO_SERVER_MSG:
                        MSG.DEMO_SERVER_MSG_RESP serverMsg_Resp = new Atomsoft.CSocket.DEMO.MSG.DEMO_SERVER_MSG_RESP(seqid);
                        this.SendBytes(serverMsg_Resp.GetBytes());
                        break;
                }

            }
            private void Send_DEMO_COMMAND(MSG.DEMO_COMMAND_ID cmdID)
            {
                switch (cmdID)
                {
                    case MSG.DEMO_COMMAND_ID.DEMO_TERMINATE:
                        MSG.DEMO_MSG_TERMINATE terminate = new MSG.DEMO_MSG_TERMINATE(this.getNextSequence());
                        this.SendBytes(terminate.GetBytes());
                        break;
                    case MSG.DEMO_COMMAND_ID.DEMO_ACTIVE_TEST:
                        MSG.DEMO_MSG_TEST active_test = new MSG.DEMO_MSG_TEST(this.getNextSequence());
                        this.SendBytes(active_test.GetBytes());
                        break;
                }

            }

            private void Send_DEMO_BIND_RESP(int result, uint seqid)
            {
                MSG.DEMO_BIND_RESP Bindresp = new Atomsoft.CSocket.DEMO.MSG.DEMO_BIND_RESP(seqid);
                Bindresp.Result = result;
                this.SendBytes(Bindresp.GetBytes());
            }
            private void Send_DEMO_BIND()
            {
                MSG.DEMO_BIND bind = new MSG.DEMO_BIND(this.getNextSequence());

                bind.UserName = "DEMO";
                bind.Password = "DEMO";
                this.SendBytes(bind.GetBytes());
                log.Msg("SendBind", "bind");
            }
            private void SendBytes(byte[] sendbytes)
            {
                this.SendBytes(sendbytes, 3);

            }

标签: 编程
来源:http://blog.csdn.net/fangaoxin/article/details/6960373

推荐: