Socket编程(二)

1.消息结构

   定义客户端和服务器之间的消息结构,便于消息的发送和接收。

   消息Message包括序号ID和消息体Body,函数GetMessageByte和GetMessage相当于消息的压缩与解压。

public class Message
{
    public Int16 ID { get; set; }
    public byte[] Body { get; set; }

    public static byte[] GetMessageByte(Message msg)
    {
        using (var stream = new MemoryStream())
        {
            using (var writer = new BinaryWriter(stream))
            {
                writer.Write(msg.ID);
                writer.Write(msg.Body.Length);
                writer.Write(msg.Body);
                return stream.ToArray();
            }
        }
    }

    public static Message GetMessage(byte[] data)
    {
        if (data == null)
        {
            return null;
        }

        Message msg = new Message();
        using (var ms = new MemoryStream(data))
        {
            using (var br = new BinaryReader(ms))
            {
                msg.ID = br.ReadInt16();
                msg.Body = br.ReadBytes(br.ReadInt32());
            }
        }
        return msg;
    }
}

2.服务器端

   服务器端启动线程,接受客户端的连接。工作线程解析客户端的数据,并发送数据回应客户端。

public class MessageServer
{
    private bool _isListening = false;
    private int _port;
    private Socket _server;
    private Thread _thListen;

    public MessageServer(int port)
    {
        _port = port;
    }

    public void Start()
    {
        if(_isListening)
            return ;
            
        try
        {         
            IPAddress address = IPAddress.Any;
            EndPoint point = new IPEndPoint(address, _port);
            //创建Socket
            _server = new Socket(address.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
            //绑定IP和端口号
            _server.Bind(point);
            //开始监听,等待客户连接
            _server.Listen(1024);

            _thListen = new Thread(ListenLoop);
            _thListen.Start();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    public void Stop()
    {
        if (!_isListening)
            return;

        try
        {
            _server.Close();
            if (_thListen.IsAlive)
            {
                _thListen.Join();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        finally
        {
            _isListening = false;
        }
    }

    private void ListenLoop()
    {
        _isListening = true;
        try
        {
            while (true)
            {
                //获取客户的Socket
                Socket client = _server.Accept();
                Thread thClient = new Thread(new ParameterizedThreadStart(HandleClient));
                thClient.Start(client);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private void HandleClient(object obj)
    {
        Socket client = obj as Socket;
        try
        {
            if (client == null)
            {
                throw new Exception("param error,not socket");
            }

            while (true)
            {
                //接收客户端的消息
                byte[] msg = ReadMessage(client);
                if (msg == null || msg.Length == 0)
                {
                    Console.WriteLine("read message failed");
                    break;
                }

                Message message = Message.GetMessage(msg);
                Message response = new Message
                {
                    ID = (short)(message.ID +1),
                    Body = message.Body
                };
                //向客户端发送数据
                WriteMessages(client, Message.GetMessageByte(response));
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        finally
        {
            try
            {
                client.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }

    private readonly int headSize = 6;
    private byte[] ReadMessage(Socket socket)
    {
        try
        {
            byte[] head = new byte[headSize];
            int cur = 0;
            do
            {
                cur += socket.Receive(head, cur, headSize - cur, SocketFlags.None);
            } while (cur < headSize);

            Int32 bodySize = 0;
            using (var br = new BinaryReader(new MemoryStream(head)))
            {
                br.ReadInt16();
                bodySize = br.ReadInt32();
            }

            if (bodySize > 0)
            {
                byte[] msg = new byte[headSize + bodySize];
                Array.Copy(head, msg, headSize);
                cur = headSize;
                bodySize += headSize;
                do
                {
                    cur += socket.Receive(msg, cur, bodySize - cur, SocketFlags.None);
                } while (cur < bodySize);

                return msg;
            }
            else
            {
                return head;
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            return null;
        }
    }

    private void WriteMessages(Socket socket, byte[] data)
    {
        if (data == null || data.Length == 0)
            return;

        try
        {
            int index = 0;
            do
            {
                index += socket.Send(data, index, data.Length - index, SocketFlags.None);
            } while (index < data.Length);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        MessageServer svr = new MessageServer (1025);
        svr.Start();
        Console.ReadLine();
        if (svr != null)
        {
            svr.Stop();
        }
    }
}

3.客户端

   客户端向服务器端发送一条数据,并接收服务器的回复。

class Program
{
    static void Main(string[] args)
    {
        //1.创建客户端socket
        Socket client = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        //2.发起建立连接的请求
        IPAddress address = IPAddress.Parse("192.168.0.4");
        EndPoint point = new IPEndPoint(address, 1025);
        client.Connect(point);

        //4.向服务器发送消息
        byte[] body = System.Text.Encoding.Default.GetBytes("Give me data!");
        Message message = new Message
        {
            ID = 2,
            Body = body
        };
        byte[] msg = Message.GetMessageByte(message);          
        WriteMessages(client,msg);

        //3.接收服务器的消息
        byte[] response = ReadMessage(client);
        Message result = Message.GetMessage(response);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值