【C#】Socket-TCP/IP通讯

1、new Socket

new Socket(AddressFamily, SocketType, ProtocolType)

AddressFamily: 指定 Socket 类的实例可以使用的寻址方案

AddressFamily.InterNetwork ==> IP版本4的地址

SocketType:套接字类型

SocketType.Stream==>支持可靠、双向、基于连接的字节流,而不重复数据,也不保留边界。 此类型的 Socket 与单个对方主机通信,并且在通信开始之前需要建立远程主机连接。 Stream 使用传输控制协议 (ProtocolType.Tcp) 和 AddressFamilyInterNetwork 地址族。

ProtocolType:支持的协议类型

ProtocolType.Tcp ==》传输控制协议

2、BeginConnect()

IAsyncResult connResult = BeginConnect(EndPoint, AsyncCallback, Object)

参数:

EndPoint: 远程主机IP和端口号信息

IPAddress ip = IPAddress.Parse(strIP);
EndPoint endpoint = new IPEndPoint(ip, port);//port为int32

AsyncCallback: 异步回调

Object:包含此请求的状态信息的对象

返回值:

IAsyncResult

AsyncWaitHandle:用于等待异步操作完成的 WaitHandle

CloseWaitOne(毫秒int32,超时结束等待bool)

IsCompleted:异步操作是否完成

3、等待连接结果

connResult.AsyncWaitHandle.WaitOne(2000, true);

4、处理等待结果

connResult.IsCompleted

成功=》返回成功,设置接收数据超时时间

socket.ReceiveTimeout = iRecvTimeOut

失败/异常=》返回失败, 关闭连接

socket.Close()

5、发送数据

socket.BeginSend(buffer, offset, size, SocketFlags, AsyncCallback, Object)

buffer : 数据包byte[]

offset: buffer 参数中开始发送数据的位置,该位置从零开始计数。

SocketFlags: 指定套接字发送和接收行为。

SocketFlags.None不对此调用使用任何标志

6、接收数据

iRecvSize = socket.Available;接收到的字节数

socket.Receive(recvData, iSize, SocketFlags.None);将接收到的数据存储到recvData

Demo:实现TCP/IP通讯

socket相关

public class SocketHelper
{
    private static SocketHelper instance;
    public static SocketHelper GetInstance()
    {
        if (instance == null)
        {
            instance = new SocketHelper();
        }
        return instance;
    }

    private Socket socket;

    private bool socketConnected;

    private SocketHelper()
    {
        socketConnected = false;
    }
    public void Connect(string ip, int port)
    {
        IPAddress IP = IPAddress.Parse(ip);
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            IAsyncResult res = socket.BeginConnect(new IPEndPoint(IP, port), null, null);
            res.AsyncWaitHandle.WaitOne(2000, true);
            if (res.IsCompleted)
            {
                socket.ReceiveTimeout = 2000;
            }
            else
            {
                socket.Close();
            }
        }
        catch (Exception)
        {
            socket.Close();
        }
    }
    public void DisConnect()
    {
        if (socketConnected)
        {
            try
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
                socketConnected = false;
            }
            catch (Exception) { }
        }
    }

    public bool SendMessage(byte[] sendBuffer, int size)
    {
        if (socketConnected)
        {
            try
            {
                socket.BeginSend(sendBuffer, 0, size, SocketFlags.None, null, null);
                return true;
            }
            catch (Exception) { }
        }
        return false;
    }

    public void ReceiveMessage(out byte[] receiveBuffer, out int size)
    {
        receiveBuffer = new byte[255];
        size = 0;
        if (socketConnected)
        {
            try
            {
                Array.Clear(receiveBuffer, 0, receiveBuffer.Length);
                size = socket.Receive(receiveBuffer);
            }
            catch (Exception) { }
        }
    }
}

TCP及数据处理相关

public class TCPHelper
{
    private static TCPHelper instance;
    public static TCPHelper GetInstance()
    {
        if (instance == null)
        {
            instance = new TCPHelper();
        }
        return instance;
    }

    private SocketHelper socket;
    private bool TCPConnected;
    
    private FeedBack_STATE state;
    private List<FeedBack_STATE> stateList;

    private TCPHelper()
    {
        TCPConnected = false;
        socket = SocketHelper.GetInstance();
        socket.Connect("192.168.10.10", 3000);

        state = new FeedBack_STATE();
        stateList = new List<FeedBack_STATE>();
    }

    public void Connect()
    {
        GetCommand(CommandType.CONNECT, out byte[] sendBuffer, out int size);
        TCPConnected = socket.SendMessage(sendBuffer, size);
    }

    public void DisConnect()
    {
        GetCommand(CommandType.DISCONNECT, out byte[] sendBuffer, out int size);
        socket.SendMessage(sendBuffer, size);
        socket.DisConnect();
        TCPConnected = false;
    }

    public void Receive(CommandType commandType)
    {
        if (!TCPConnected) return;
        GetCommand(commandType, out byte[] sendBuffer, out int size);
        socket.SendMessage(sendBuffer, size);
        ParseReceiveData();
    }

    private void ParseReceiveData()
    {
        if (!TCPConnected) return;
        socket.ReceiveMessage(out byte[] receiveBuffer, out int size);
        if (size == 0) return;
        FeedBack_Header header = StructToBytes.BytesToStruct<FeedBack_Header>(receiveBuffer, 0);
        switch (header.commandType)
        {
            case (ushort)CommandType.STATE:
                state = StructToBytes.BytesToStruct<FeedBack_STATE>(receiveBuffer, Marshal.SizeOf(header));
                break;
            case (ushort)CommandType.STATELIST:
                stateList.Clear();
                int offset = Marshal.SizeOf(typeof(FeedBack_STATE));
                int num = header.dataLen / offset;
                StructToBytes.BytesToStruct(receiveBuffer, Marshal.SizeOf(header), offset, num, ref stateList);
                break;
            default:
                break;
        }
    }

    private void GetCommand(in CommandType commandType, out byte[] sendBuffer, out int size)
    {
        Command header;
        header.commandType = (ushort)commandType;
        sendBuffer = StructToBytes.StructToByte(header);
        size = Marshal.SizeOf(header);
    }

    public List<FeedBack_STATE> GetStateList() {
        return this.stateList;
    }

    public FeedBack_STATE GetState()
    {
        return this.state;
    }
}

数据显示

public class UI_ShowData{
    private void Start() {
        TCPHelper tcp = TCPHelper.GetInstance();
        tcp.Connect();

        tcp.Receive(CommandType.STATELIST);
        List<FeedBack_STATE> stateList = tcp.GetStateList();
    
        tcp.Receive(CommandType.STATE);
        FeedBack_STATE state = tcp.GetState();
    
        tcp.DisConnect();
    }
}

数据结构定义

public class DataStructDefine
{
    public enum CommandType : ushort
    {
        CONNECT = 0x1000,
        DISCONNECT = 0x1001,

        STATE = 0x2001,
        STATELIST = 0x2002,
    }
    
    public struct Command
    {
        public ushort commandType;
    }
    public struct FeedBack_Header
    {
        public ushort commandType;
        public int dataLen;
    }
    public struct FeedBack_STATE
    {
        public int id;
        public float position;
    }
}

字节和结构体相互转换

public class StructToBytes
{
    public static byte[] StructToByte(object structObj)
    {
        int size = Marshal.SizeOf(structObj);
        byte[] _bytes = new byte[size];
        IntPtr structPtr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(structObj, structPtr, false);
        Marshal.Copy(structPtr, _bytes, 0, size);
        Marshal.FreeHGlobal(structPtr);
        return _bytes;
    }

    public static T BytesToStruct<T>(byte[] buff, int StartIndex)
    {
        object Structure = null;
        int size = Marshal.SizeOf(typeof(T));

        IntPtr structPtr = Marshal.AllocHGlobal(size);
        Marshal.Copy(buff, StartIndex, structPtr, size);
        Structure = Marshal.PtrToStructure(structPtr, typeof(T));
        Marshal.FreeHGlobal(structPtr);
        return (T)Structure;
    }

    public static void BytesToStruct<T>(byte[] buff, int StartIndex, int offset, int addNum, ref List<T> list)
    {
        int count = 0;
        int start = 0;
        while (count < addNum)
        {
            start = StartIndex + count * offset;
            list.Add(BytesToStruct<T>(buff, start));
            count++;
        }
    }

    public static object BytesToStruct(byte[] buff, int StartIndex, Type type)
    {
        int size = Marshal.SizeOf(type);
        IntPtr structPtr = Marshal.AllocHGlobal(size);
        Marshal.Copy(buff, StartIndex, structPtr, size);
        object obj = Marshal.PtrToStructure(structPtr, type);
        Marshal.FreeHGlobal(structPtr);
        return obj;
    }
}
posted @ 2024-10-09 08:47  Sitar  阅读(144)  评论(0编辑  收藏  举报