【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) 和 AddressFamily
。InterNetwork 地址族。
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
Close
、WaitOne(毫秒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;
}
}