Socket 基础&实例(上)

来源:互联网 发布:codeblocks有mac版吗 编辑:程序博客网 时间:2024/05/16 04:43

Socket 基础知识

  1. TCP/IP层次模型

    a. 应用层
    b. 传输层 : UDP和TCP(区别即 TCP传输控制协议,是一种提供可靠数据传输的通用协议。
         UDP是一个面 向无连接的协议,此处可能解释不太清楚,百度哈。(~ o ~)~zZ)
    c. 网络层:通信子网,它通过网络连接交换传输层发出的实体数据。
    d. 链路层:是建立在物理传输能力的基础上,以帧为单位传输数据,
         它的主要任务就是进行数据封装和数据链接的建立

    TCP分节传输图解
    这里写图片描述
    (每层传输过程中,都将增加分节的头)

  2. Socket类型

    a. 流式Socket
     是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低
    b. 数据报式Socket
     是一种无连接的Socket,对应于无连接的UDP服务应用,不安全,但效率高

     组图说明Socket客户端和服务器的连接过程
    这里写图片描述
    这就是所谓的三次握手,哈哈。。

  3. Socket常用类和方法

    相关类:

    IPAddress:包含了一个IP地址    IPEndPoint:包含了一对IP地址和端口号

方法:

    Socket():创建一个Socket    Bind():绑定一个本地的IP和端口号(IPEndPoint)    Listen():让Socket侦听传入的连接吃那个病,并指定侦听队列容量    Connect():初始化与另一个Socket的连接    Accept():接收连接并返回一个新的Socket    Send():输出数据到Socket    Receive():从Socket中读取数据

上方法在Socket连接中基本上都会用到

  1. 实战部分代码

服务器代码(新建项目的时候,此处是
这里写图片描述

using System;using System.Net;using System.Collections.Generic;using System.Net.Sockets;using System.IO;using System.Text;using System.Threading;using System.Runtime.Serialization.Formatters.Binary;public class Echoserver{    private static int m_SocketCount = 0;    private static ManualResetEvent m_ManualResetEvent = new ManualResetEvent(false);    //entry point of main method.    public static void Main()    {        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10068);        Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);        try        {            serverSocket.Bind(ipEndPoint);            serverSocket.Listen(20);            Console.WriteLine("Server Start");            while (true)            {                m_ManualResetEvent.Reset(); //将线程置于非终止状态,也就是等待当前线程完成;                serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);                m_ManualResetEvent.WaitOne(); //阻塞主线程,这里的作用是不退出程序;            }        }        catch (System.Exception ex)        {            Console.WriteLine("Exception" + ex);        }    }    public static void Accept(IAsyncResult result)    {        m_ManualResetEvent.Set(); //通知主线程继续;        Socket serverSocket = (Socket)result.AsyncState;        Console.WriteLine("Accept one Client " + (++m_SocketCount));        //已经Accept客户端之后就停止Accept;        Socket receiverSocket = serverSocket.EndAccept(result);        //开始Receive;        StateObject state = new StateObject();        state.m_CurSocket = receiverSocket;        receiverSocket.BeginReceive(state.m_Buffer, 0, StateObject.m_BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);    }    public static void ReceiveCallBack(IAsyncResult result)    {        String content = String.Empty;        StateObject state = (StateObject)result.AsyncState;        Socket receiverSocket = state.m_CurSocket;        try        {            int byteRead = receiverSocket.EndReceive(result);            if (byteRead > 0)            {                //获取数据长度;                byte[] datalengtharr = new byte[4];                Buffer.BlockCopy(state.m_Buffer, 0, datalengtharr, 0, 4);                int datalength = BitConverter.ToInt32(datalengtharr, 0);                Console.WriteLine("receive data length = " + datalength.ToString());                //获取数据主体;                byte[] dataarr = new byte[byteRead - 4];                Buffer.BlockCopy(state.m_Buffer, 4, dataarr, 0, byteRead - 4);                state.m_StringBuilder.Append(Encoding.ASCII.GetString(dataarr, 0, byteRead - 4));                content = state.m_StringBuilder.ToString();                //判断数据长度,是否接收完全;                if (!(byteRead - 4 < datalength))                {                    Console.WriteLine("Receive " + content.Length + "  " + content);                    //接收完全后发送数据给客户端;                    Send(receiverSocket, "success from server");                }                else                {                    //数据没有接收完,继续接收;                    receiverSocket.BeginReceive(state.m_Buffer, 0, StateObject.m_BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);                }            }        }        catch (Exception ex)        {            Console.WriteLine(ex.ToString());        }    }    public static void Send(Socket handler, String data)    {        byte[] byteData = Encoding.ASCII.GetBytes(data);        try        {            handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);        }        catch (Exception ex)        {            Console.WriteLine(ex.ToString());        }    }    public static void SendCallback(IAsyncResult result)    {        try        {            Socket handler = (Socket)result.AsyncState;            int bytesSend = handler.EndSend(result);            Console.WriteLine("Sent {0} bytes to client.", bytesSend);            handler.Shutdown(SocketShutdown.Both);            handler.Close();        }        catch (System.Exception ex)        {            Console.WriteLine(ex.ToString());        }    }    public class StateObject    {        public Socket m_CurSocket = null;        public const int m_BufferSize = 1024;        public byte[] m_Buffer = new byte[m_BufferSize];        public StringBuilder m_StringBuilder = new StringBuilder();    }}

客户端代码

using UnityEngine;using UnityEngine.UI;using System.Collections;using System.Collections.Generic;using System;using System.Net;using System.Net.Sockets;using System.Text;using System.IO;using System.Runtime.Serialization.Formatters.Binary;using System.Runtime.Serialization;public class Test : MonoBehaviour{    /// <summary>    /// 连接到服务器    /// </summary>    public void AsynConnect()    {        //端口及IP        IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10068);        //创建套接字        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);        //开始连接到服务器        client.BeginConnect(ipe, asyncResult =>        {            client.EndConnect(asyncResult);            //向服务器发送消息            DataMsg msg = new DataMsg();            msg.indexPos = 5;            msg.name = "宏宇";            msg.sex = 1;            List<string> otherPerList = new List<string>();            otherPerList.Add("小鸭");            otherPerList.Add("斗鸡");            otherPerList.Add("斗鸟");            msg.otherPerList.AddRange(otherPerList);            //AsynSend(client, msg);            AsynSend(client, "你好我是客户端");            //AsynSend(client, "第一条消息");            //AsynSend(client, "第二条消息");            //接受消息            AsynRecive(client);        }, null);    }    /// <summary>    /// 发送消息    /// </summary>    /// <param name="socket"></param>    /// <param name="message"></param>    public void AsynSend(Socket socket, string message)    {        if (socket == null || message == string.Empty) return;        //编码        byte[] data = Encoding.UTF8.GetBytes(message);        try        {            socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>            {                //完成发送消息                int length = socket.EndSend(asyncResult);                Debug.Log(string.Format("客户端发送消息:{0}", message));            }, null);        }        catch (Exception ex)        {            Debug.Log(string.Format("异常信息:{0}", ex.Message));        }    }    public void AsynSend(Socket socket, DataMsg msgData)    {        if (socket == null || msgData == null)        {            return;        }        Debug.Log(msgData);        MemoryStream mStream = new MemoryStream();        //BinaryFormatter bFormatter = new BinaryFormatter();        BinaryFormatter iFormatter = new BinaryFormatter();        //bFormatter.Serialize(mStream, msgData);        //bFormatter.Serialize(mStream, "fff");        iFormatter.Serialize(mStream, msgData);        mStream.Flush();        byte[] buffer = new byte[1024];        mStream.Position = 0;        while (mStream.Read(buffer, 0, buffer.Length) > 0)        {            socket.Send(buffer);        }        socket.Close();        Debug.Log("数据发送完毕");    }    /// <summary>    /// 接收消息    /// </summary>    /// <param name="socket"></param>    public void AsynRecive(Socket socket)    {        byte[] data = new byte[1024];        try        {            //开始接收数据            socket.BeginReceive(data, 0, data.Length, SocketFlags.None,            asyncResult =>            {                int length = socket.EndReceive(asyncResult);                Debug.Log(string.Format("收到服务器消息:{0}", Encoding.UTF8.GetString(data)));                //AsynRecive(socket);            }, null);        }        catch (Exception ex)        {            Debug.Log(string.Format("异常信息:", ex.Message));        }    }    void Awake()    {        gameObject.GetComponent<Button>().onClick.AddListener(delegate()        {            OnClickEvent(gameObject);        });    }    void OnClickEvent(GameObject target)    {        Debug.Log("Click" + target.name);        AsynConnect();    }}[Serializable]public class DataMsg{    public int indexPos;    public int sex;    public string name;    public List<string> otherPerList;    public DataMsg()    {        indexPos = 0;        sex = 0;        name = string.Empty;        otherPerList = new List<string>();    }}

大家可能也注意到了我这里的客户端,留有传序列化的数据的方法,没错,本次实验只做传输数据,字符串简单的数据,后面会涉及多终端对一个服务器时的数据传输,等等,一直研究下去

如果有错误的地方,请指点,比较晚了,不好的下次再更新

1 0