在前一篇讲到了服务侦听,具体构建了一个抽象类,该类是后续服务类中SOCKET通讯服务的基类,而SOCKET通讯中不论是服务端还是客户端都需要数据收发,客户端对应服务端侦听的部份则是连接,下面就讲讲连接和数据收发
1.连接
该部份比较简单,只有三个简单的函数:CreateConnectToRemoteSocket,ConnectToRemoteCore,AsyncConnectToRemoteCore,
CreateConnectToRemoteSocket:创建连接的Socket,其中CheckSockectIsConnected是检查是否已连接(该函数用了MS使用的例子来判断是否已连接),最后使用传进的参数(如果不为null)设置SOCKET(比如超时等等),TcpIPSocketSetting类是一个专用户设置SOCKET的类
ConnectToRemoteCore:同步连接到远程
AsyncConnectToRemoteCore:异步连接到远程,在该函数中用到类接口ITranseParamets,使用SocketAsyncEventArgs.UserToken存储该接口参数,对于该接口的定义我会在代码中贴出,并且属性及方法也会在该接口中说明,其实现会在后续章节中讲到,SocketAsyncEventArgs.RemoteEndPoint存储要连接到的远程终结点(这个一定要设),最后调用Socket.ConnectAsync函数异步连接,该函数使用的参数及返回值的含义等同上一章使用到的Socket.AcceptAsync,在Socket中类似这样的还有收发函数Socket.SendAsync,Socket.ReceiveAsync,这些函数都使用SocketAsyncEventArgs类,返回值都是Bool类型,含义及处理都类型上一章的Socket.AcceptAsync,只是在调用前设置SocketAsyncEventArgs类的方法不同(而所有方法中都必需设置SocketAsyncEventArgs.Completed事件),及返回后SocketAsyncEventArgs类的有效属性不同,本例中是在GetSocketArg方法中设置了SocketAsyncEventArgs类的属性,由于GetSocketArg是一个通用方法,其实在本例中它仅设置类SocketError属性及Completed事件,其它属性都是null,本例中Socket.ConnectAsync方法完成后的有效属性:它完成后仅SocketError属性有效指示是否成功
OnCompleted:Completed事件处理程序,该例程是连接及数据收发的处理例程,先讲连接的处理例程,仅仅调用OnConnectCompleted方法完成连接
OverAsyncTranse:该例程用于完成异步操作,它在连接及收发操作中都会调用,首先RecySocketAsyncEventArgs,回收SocketAsyncEventArgs,如果你的SocketAsyncEventArgs不是使用缓冲的则不必调用了,设置ITranseParamets.TranseError指示是否有错误,调用ITranseParamets.AsyncTranseOver通指异步操作完成
2.数据收发的约定
数据的收发方都遵循约定ITranseHeader,该接口是一个约定,及传输过程中的控制信息,实现该接口的类负责解读该约定的含义,而该接口在网络中传输的数据则存储在该接口的Data属性中,Data属性应该是一个接收双方都已知长度的字节数组,通常方送方事先填充Data,接收方根据双方已知的字节长度接收该长度字节数的内容,具体说命见代码中贴出的说明,
其实现会在后续章节中给出,其实这个就类似于数据传输协议的头
3.数据的收发
数据收发分为同步和异步两种,这两种都用同一规则操作,只不过途经不同而已,它们都是:先发送(接收)约定,然后根据约定发送(接收)数据体,同步接收和发送比较简单,分别是SendDataCore,ReceiveDataCore这两个例程,而它们又都各自调用SendHeaderCore和ReceiveHeaderCore来发送(接收)约定
PrepareForSend:发送前准备,将要发送的数据读到发送缓冲区,这个例程同步和异步都使用,看过程就应该知道起含义,这里就不说了
HandlerReceiver:接收数据后的处理,该例程将接收到的字节数rcvsize写进流中,并根据约定返回是否还有后续数据要接收,同样这个例程同步异步都使用
数据异步的收发:AsyncSendDataCore和AsyncRecevDataCore分别发送和接收约定,NextAsyncSendDataCore和NextAsyncReceiveDataCore分别根据约定发送和接收数据体,返回True说明还有后续数据需要发送或接收,否则说明数据发送或接收完成,HeaderIsTranseOver例程判断约定是否已发送或接收完成,在异步数据收发中最重要的是设置每次要发送或接收的数据缓冲区(该缓冲区在给出SocketAsyncEventArgs就已设为ITranseParamets.TranseBuffer)及偏移量和长度,而偏移量及长度分别在发送和接收前设置
OnCompleted:数据异步接收和发送事件处理
约定完成前调用OnHeaderCompleted,约定完成后调用OnTranseDataCompleted,这两个例程都是判断指定操作是否已完成,未完成则继续下一轮操作,OnHeaderCompleted例程中已完成则开始根据约定开始数据主体收发操作,OnTranseDataCompleted例程中完成则调用OverAsyncTranse结束异步操作
3.其它
ITranseInterface接口是为了以后扩展数据传输而定义的接口(例如不使用Socket的数据传输),在使用中仅使用该接口而不管其实现,这样方便以后扩展
本类中TranseInterfaceDirection枚举是为了区分该传输接口是客户端连接发起方还是服务端被动接受连接方,分别提供两个构造,带参数的构造一定是服务端被动接收端,不带参数的构造则是客户端发起连接方
WaitClose方法和Close方法:前一个方法是等待远程方调用Close后才关闭,其实现机理是首先开始异步接收1长度数据等待对方关闭时肯定在回调中引发错误,此时关闭.
以下为代码:
TcpIpTranseInterface
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 using System.Net; 8 9 namespace YZKStdLibrary.Network.Transe 10 { 11 public class TcpIpTranseInterface : ITranseInterface 12 { 13 14 static TcpIpTranseInterface() 15 { 16 StateSendBytes = new byte[1]; 17 SocketArgPools = new RecyManager<SocketAsyncEventArgs>(50); 18 WaitCloseBytes = new byte[1]; 19 } 20 21 public TcpIpTranseInterface() 22 { 23 p_TranseDirection = TranseInterfaceDirection.Client; 24 } 25 26 public TcpIpTranseInterface( 27 Socket socket) 28 { 29 g_TcpSocket = socket; 30 p_TranseDirection = TranseInterfaceDirection.Server; 31 } 32 33 internal Socket BaseSocket 34 { 35 get { return g_TcpSocket; } 36 } 37 38 #region 私有变量 39 40 private Socket g_TcpSocket; 41 42 private TranseInterfaceDirection p_TranseDirection; 43 44 private static readonly byte[] StateSendBytes; 45 46 private static readonly byte[] WaitCloseBytes; 47 48 public static readonly RecyManager<SocketAsyncEventArgs> SocketArgPools; 49 50 #endregion 51 52 #region ITranseInterfaceInformation 成员 53 /// <summary> 54 /// 获取本地终结点信息 55 /// </summary> 56 public EndPoint LocalEndPont 57 { 58 get 59 { 60 if (g_TcpSocket != null) 61 return g_TcpSocket.LocalEndPoint; 62 else 63 return null; 64 } 65 } 66 /// <summary> 67 /// 获取远程终结点信息 68 /// </summary> 69 public EndPoint RemoteEndPoint 70 { 71 get 72 { 73 if (g_TcpSocket != null) 74 return g_TcpSocket.RemoteEndPoint; 75 else 76 return null; 77 } 78 } 79 /// <summary> 80 /// 获取当前传输接口建立连接时的方向 81 /// </summary> 82 public TranseInterfaceDirection TranseDirection 83 { 84 get { return p_TranseDirection; } 85 } 86 /// <summary> 87 /// 获取传输协义名称 88 /// </summary> 89 public string ProtocolTypeName 90 { 91 get { return TranseProtocolTypeNames.TcpIp; } 92 } 93 94 #endregion 95 96 #region 接收前和发送后流处理 97 98 /// <summary> 99 /// 返回小于等于0值指示无数据发送100 /// 会设置paramets.BytesTransferred101 /// </summary>102 /// <param name="paramets"></param>103 /// <returns></returns>104 private int PrepareForSend(ITranseParamets paramets)105 {106 int rd = paramets.TranseStream.Read(107 paramets.TranseBuffer, paramets.TranseBufferOffset, paramets.TranseBufferSize);108 if (rd > 0)109 {110 paramets.BytesTransferred =111 paramets.BytesTransferred + rd;112 }113 return rd;114 }115 116 /// <summary>117 /// 返回True指示已接收完成118 /// 会设置paramets.BytesTransferred119 /// </summary>120 /// <param name="paramets"></param>121 /// <param name="rcvsize"></param>122 /// <returns></returns>123 private bool HandlerReceiver(ITranseParamets paramets,int rcvsize)124 {125 if (rcvsize > 0)126 {127 paramets.TranseStream.Write(paramets.TranseBuffer,128 paramets.TranseBufferOffset, rcvsize);129 paramets.BytesTransferred =130 paramets.BytesTransferred + rcvsize;131 }132 return paramets.TranseHeader.TranseSize <= paramets.BytesTransferred;133 }134 #endregion135 136 #region 数据同步接收和发送137 138 private void SendHeaderCore(139 ITranseHeader header)140 {141 int offset = 0;142 int l = header.Data.Length;143 while (l > 0)144 {145 int s = g_TcpSocket.Send(header.Data, offset, l, SocketFlags.None);146 l -= s;147 offset += s;148 }149 }150 151 private void SendDataCore(ITranseParamets paramets)152 {153 SendHeaderCore(paramets.TranseHeader);154 paramets.HeaderTransed();155 int x = PrepareForSend(paramets);156 while (x > 0)157 {158 while (x > 0)159 {160 int offset = paramets.TranseBufferOffset;161 int s = g_TcpSocket.Send(paramets.TranseBuffer,162 offset, x, SocketFlags.None);163 x -= s;164 offset += s;165 }166 x = PrepareForSend(paramets);167 }168 }169 170 private void ReceiveHeaderCore(171 ITranseHeader header)172 {173 int l = header.Data.Length;174 int offset = 0;175 while (l > 0)176 {177 int s = g_TcpSocket.Receive(header.Data, offset, l, SocketFlags.None);178 l -= s;179 offset += s;180 }181 header.ResetParametsFromData();182 }183 184 private void ReceiveDataCore(ITranseParamets paramets)185 {186 ReceiveHeaderCore(paramets.TranseHeader);187 paramets.HeaderTransed();188 int rcvsize = 0;189 while (!HandlerReceiver(paramets, rcvsize))190 {191 long x = paramets.TranseHeader.TranseSize - paramets.BytesTransferred;192 if (x > paramets.TranseBufferSize)193 x = paramets.TranseBufferSize;194 rcvsize = g_TcpSocket.Receive(paramets.TranseBuffer,195 paramets.TranseBufferOffset, (int)x, SocketFlags.None);196 }197 }198 #endregion199 200 #region 异步处理201 202 private void CopyHeaderDataToTranseBuffer(203 ITranseParamets par,SocketAsyncEventArgs arg)204 {205 int hs = par.TranseHeader.Data.Length;206 arg.SetBuffer(arg.Offset, hs);207 Array.Copy(par.TranseHeader.Data, 0, arg.Buffer,208 arg.Offset, arg.Count);209 }210 211 private void CopyTranseBufferToHeaderData(212 ITranseParamets par, SocketAsyncEventArgs arg)213 {214 int hs = par.TranseHeader.Data.Length;215 Array.Copy(arg.Buffer, arg.Offset,216 par.TranseHeader.Data, 0, hs);217 par.TranseHeader.ResetParametsFromData();218 }219 220 private SocketAsyncEventArgs GetSocketArg(221 ITranseParamets par)222 {223 SocketAsyncEventArgs arg = SocketArgPools.GetItem();224 arg.SetBuffer(par.TranseBuffer, par.TranseBufferOffset, par.TranseBufferSize);225 arg.Completed += new EventHandler<SocketAsyncEventArgs>(OnCompleted);226 arg.SocketError = SocketError.Success;227 return arg;228 }229 230 private void RecySocketAsyncEventArgs(SocketAsyncEventArgs arg)231 {232 arg.Completed -= new EventHandler<SocketAsyncEventArgs>(OnCompleted);233 arg.SetBuffer(null, 0, 0);234 arg.UserToken = null;235 arg.AcceptSocket = null;236 arg.RemoteEndPoint = null;237 SocketArgPools.RecyItem(arg);238 }239 240 private void OverAsyncTranse(241 SocketAsyncEventArgs arg,242 ITranseParamets paramets,243 Exception error)244 {245 RecySocketAsyncEventArgs(arg);246 paramets.TranseError = error;247 paramets.AsyncTranseOver();248 }249 250 private void OnCompleted(object sender, SocketAsyncEventArgs e)251 {252 ITranseParamets par = e.UserToken as ITranseParamets;253 if (par.DataTranseDirection != DataTranseDirection.Connecting)254 {255 if (e.BytesTransferred == 0)256 {257 if (!CheckSockectIsConnected())258 e.SocketError = SocketError.ConnectionAborted;259 }260 }261 if (e.SocketError != SocketError.Success)262 {263 OverAsyncTranse(e, par, new SocketException((int)e.SocketError));264 return;265 }266 switch (par.DataTranseDirection)267 {268 case DataTranseDirection.Connecting:269 {270 OnConnectCompleted(par,e);271 break;272 }273 case DataTranseDirection.ReceivingData:274 case DataTranseDirection.SendingData:275 {276 if (par.HeaderTransedOver)277 OnTranseDataCompleted(par,e);278 else279 OnHeaderCompleted(par,e);280 break;281 }282 }283 }284 285 private void OnHeaderCompleted(ITranseParamets paramets,SocketAsyncEventArgs e)286 {287 bool ovcall = false;288 switch (e.LastOperation)289 {290 case SocketAsyncOperation.Send:291 {292 try293 {294 if (!HeaderIsTranseOver(paramets, e))295 {296 if (!g_TcpSocket.SendAsync(e))297 OnCompleted(g_TcpSocket, e);298 return;299 }300 paramets.HeaderTransed();301 if (!NextAsyncSendDataCore(paramets, e))302 {303 paramets.AsyncNotyTransing();304 ovcall = true;305 OverAsyncTranse(e, paramets, null);306 }307 }308 catch (Exception err)309 {310 if (!ovcall)311 OverAsyncTranse(e, paramets, err);312 }313 break;314 }315 case SocketAsyncOperation.Receive:316 {317 try318 {319 if (!HeaderIsTranseOver(paramets, e))320 {321 if (!g_TcpSocket.ReceiveAsync(e))322 OnCompleted(g_TcpSocket, e);323 return;324 }325 CopyTranseBufferToHeaderData(paramets, e);326 paramets.HeaderTransed();327 if (!NextAsyncReceiveDataCore(paramets, e))328 {329 ovcall = true;330 OverAsyncTranse(e, paramets, null);331 }332 }333 catch (Exception err)334 {335 if (!ovcall)336 OverAsyncTranse(e, paramets, err);337 }338 break;339 }340 }341 }342 343 private void OnConnectCompleted(ITranseParamets paramets,SocketAsyncEventArgs e)344 {345 OverAsyncTranse(e, paramets, null);346 }347 348 private void OnTranseDataCompleted(ITranseParamets paramets,SocketAsyncEventArgs e)349 {350 bool ovcall = false;351 switch (e.LastOperation)352 {353 case SocketAsyncOperation.Send:354 {355 try356 {357 paramets.AsyncNotyTransing();358 if (!NextAsyncSendDataCore(paramets, e))359 {360 ovcall = true;361 OverAsyncTranse(e, paramets, null);362 }363 }364 catch (Exception err)365 {366 if (!ovcall)367 OverAsyncTranse(e, paramets, err);368 }369 break;370 }371 case SocketAsyncOperation.Receive:372 {373 try374 {375 bool hd = HandlerReceiver(paramets, e.BytesTransferred);376 paramets.AsyncNotyTransing();377 if (hd)378 {379 ovcall = true;380 OverAsyncTranse(e, paramets, null);381 }382 else383 {384 NextAsyncReceiveDataCore(paramets, e);385 }386 }387 catch (Exception err)388 {389 if (!ovcall)390 OverAsyncTranse(e, paramets, err);391 }392 break;393 }394 }395 }396 397 #endregion398 399 }400 401 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 using System.Net; 8 9 namespace YZKStdLibrary.Network.Transe 10 { 11 partial class TcpIpTranseInterface : ITranseInterface 12 { 13 #region 数据异步接收和发送 14 15 private bool NextAsyncSendDataCore(ITranseParamets paramets, SocketAsyncEventArgs e) 16 { 17 int s = PrepareForSend(paramets); 18 if (s > 0) 19 { 20 if (s > paramets.TranseBufferSize) 21 s = paramets.TranseBufferSize; 22 e.SetBuffer(e.Offset, s); 23 if (!g_TcpSocket.SendAsync(e)) 24 OnCompleted(g_TcpSocket, e); 25 return true; 26 } 27 return false; 28 } 29 30 private void AsyncSendDataCore(ITranseParamets par) 31 { 32 SocketAsyncEventArgs arg = GetSocketArg(par); 33 arg.UserToken = par; 34 CopyHeaderDataToTranseBuffer(par, arg); 35 if (!g_TcpSocket.SendAsync(arg)) 36 OnCompleted(g_TcpSocket, arg); 37 } 38 39 private void AsyncRecevDataCore(ITranseParamets par) 40 { 41 SocketAsyncEventArgs arg = GetSocketArg(par); 42 arg.UserToken = par; 43 arg.SetBuffer(arg.Offset, par.TranseHeader.Data.Length); 44 if (!g_TcpSocket.ReceiveAsync(arg)) 45 OnCompleted(g_TcpSocket, arg); 46 } 47 48 private bool NextAsyncReceiveDataCore(ITranseParamets paramets, SocketAsyncEventArgs e) 49 { 50 long dx = paramets.TranseHeader.TranseSize - paramets.BytesTransferred; 51 if (dx > 0) 52 { 53 if (dx > paramets.TranseBufferSize) 54 dx = paramets.TranseBufferSize; 55 e.SetBuffer(e.Offset, (int)dx); 56 if (!g_TcpSocket.ReceiveAsync(e)) 57 OnCompleted(g_TcpSocket, e); 58 return true; 59 } 60 return false; 61 } 62 63 private bool HeaderIsTranseOver(ITranseParamets paramets, SocketAsyncEventArgs e) 64 { 65 int dx = e.Count - e.BytesTransferred; 66 if (dx > 0) 67 { 68 int offset = e.Offset + e.BytesTransferred; 69 e.SetBuffer(offset, dx); 70 return false; 71 } 72 else 73 e.SetBuffer(paramets.TranseBufferOffset, paramets.TranseBufferSize); 74 return true; 75 } 76 #endregion 77 78 #region 异步等待对方关闭 79 80 private void WaitCloseCore(object state, WaitCloseDelegate callback) 81 { 82 lock (g_CloseAsyncLock) 83 { 84 if (g_TcpSocket != null 85 && !p_ClosedOver) 86 g_TcpSocket.BeginReceive(WaitCloseBytes, 87 0, 1, SocketFlags.None, WaitCloseCallback, new waitCloseParamets(state, callback)); 88 } 89 } 90 91 private void WaitCloseCallback(IAsyncResult ir) 92 { 93 waitCloseParamets callback = ir.AsyncState as waitCloseParamets; 94 lock (g_CloseAsyncLock) 95 { 96 if (!p_ClosedOver) 97 { 98 try 99 {100 g_TcpSocket.EndReceive(ir);101 }102 catch { }103 }104 }105 CloseCore(false);106 //g_TcpSocket = null;107 if (callback.Callback != null)108 callback.Callback(callback.State);109 }110 111 private class waitCloseParamets112 {113 internal waitCloseParamets(object userstate, WaitCloseDelegate usercallback)114 {115 state = userstate;116 callback = usercallback;117 }118 119 private object state;120 121 private WaitCloseDelegate callback;122 123 public object State124 {125 get { return state; }126 }127 128 public WaitCloseDelegate Callback129 {130 get131 {132 return callback;133 }134 }135 }136 #endregion137 138 #region 连接139 140 private void CreateConnectToRemoteSocket(TcpIPSocketSetting setting)141 {142 if (CheckSockectIsConnected())143 throw new InvalidOptionException("已连接");144 lock (g_CloseAsyncLock)145 {146 p_ClosedOver = false;147 g_TcpSocket = new Socket(AddressFamily.InterNetwork,148 SocketType.Stream, ProtocolType.Tcp);149 }150 if (setting != null)151 setting.AppSetting(g_TcpSocket);152 }153 154 private void ConnectToRemoteCore(EndPoint remoteEp, TcpIPSocketSetting setting)155 {156 CreateConnectToRemoteSocket(setting);157 g_TcpSocket.Connect(remoteEp);158 }159 160 private void AsyncConnectToRemoteCore(ITranseParamets par)161 {162 CreateConnectToRemoteSocket(par.ConnectTranseInterfaceSetting as TcpIPSocketSetting);163 SocketAsyncEventArgs arg = GetSocketArg(par);164 arg.UserToken = par;165 arg.RemoteEndPoint = par.ConnectToEndPoint;166 if (!g_TcpSocket.ConnectAsync(arg))167 OnCompleted(g_TcpSocket, arg);168 }169 #endregion170 171 #region 是否已连接172 173 private bool CheckSockectIsConnected(Socket socket)174 {175 lock (g_CloseAsyncLock)176 {177 if (p_ClosedOver)178 return false;179 bool bs = socket.Blocking;180 socket.Blocking = false;181 try182 {183 socket.Send(StateSendBytes, 0, SocketFlags.None);184 }185 catch (SocketException e)186 {187 // 10035 == WSAEWOULDBLOCK188 if (!e.NativeErrorCode.Equals(10035))189 return false;190 }191 finally192 {193 socket.Blocking = bs;194 }195 return socket.Connected;196 }197 }198 199 private bool CheckSockectIsConnected()200 {201 if (g_TcpSocket != null)202 return CheckSockectIsConnected(g_TcpSocket);203 else204 return false;205 }206 207 #endregion208 209 #region ITranseInterfaceTranse 成员210 211 private bool p_ClosedOver = false;212 213 private object g_CloseAsyncLock = new object();214 215 private void CloseCore(bool settonull)216 {217 lock (g_CloseAsyncLock)218 {219 if (p_ClosedOver) return;220 p_ClosedOver = true;221 if (g_TcpSocket != null)222 {223 try224 {225 g_TcpSocket.Shutdown(SocketShutdown.Both);226 }227 catch { }228 try229 {230 g_TcpSocket.Close();231 }232 catch { }233 //if (settonull)234 // g_TcpSocket = null;235 }236 }237 }238 239 public void TranseData(ITranseParamets transeparamets)240 {241 if (transeparamets.IsAsyncTranse)242 {243 switch (transeparamets.DataTranseDirection)244 {245 case DataTranseDirection.Connecting:246 {247 AsyncConnectToRemoteCore(transeparamets);248 break;249 }250 case DataTranseDirection.SendingData:251 {252 AsyncSendDataCore(transeparamets);253 break;254 }255 case DataTranseDirection.ReceivingData:256 {257 AsyncRecevDataCore(transeparamets);258 break;259 }260 }261 }262 else263 {264 switch (transeparamets.DataTranseDirection)265 {266 case DataTranseDirection.Connecting:267 {268 ConnectToRemoteCore(transeparamets.ConnectToEndPoint,269 transeparamets.ConnectTranseInterfaceSetting as TcpIPSocketSetting);270 break;271 }272 case DataTranseDirection.SendingData:273 {274 SendDataCore(transeparamets);275 break;276 }277 case DataTranseDirection.ReceivingData:278 {279 ReceiveDataCore(transeparamets);280 break;281 }282 }283 }284 }285 286 public void Close()287 {288 CloseCore(true);289 }290 291 public bool IsConnected292 {293 get { return CheckSockectIsConnected(); }294 }295 296 public void WaitClose(object state, WaitCloseDelegate callback)297 {298 try299 {300 WaitCloseCore(state, callback);301 }302 catch303 {304 CloseCore(false);305 if (callback != null)306 callback(state);307 //g_TcpSocket = null;308 }309 }310 #endregion311 312 public override string ToString()313 {314 string x = ProtocolTypeName;315 x += "{";316 x += TranseDirection.ToString() + ";";317 Socket s = g_TcpSocket;318 if (s != null)319 {320 if (s.LocalEndPoint != null)321 x += s.LocalEndPoint.ToString();322 if (s.RemoteEndPoint != null)323 x += "->" + s.RemoteEndPoint.ToString();324 }325 else326 x += "socket is null";327 x += "}";328 return x;329 }330 }331 332 }
interface
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 using System.Net; 8 9 namespace YZKStdLibrary.Network.Transe 10 { 11 public interface ITranseParamets 12 { 13 /// <summary> 14 /// 传输头 15 /// </summary> 16 ITranseHeader TranseHeader { get; } 17 /// <summary> 18 /// 传输流 19 /// </summary> 20 Stream TranseStream { get; } 21 /// <summary> 22 /// 传输缓冲区 23 /// </summary> 24 byte[] TranseBuffer { get; } 25 /// <summary> 26 /// 传输缓冲区的偏移量 27 /// </summary> 28 int TranseBufferOffset { get; } 29 /// <summary> 30 /// 传输缓冲区从TranseBufferOffset开始的大小 31 /// </summary> 32 int TranseBufferSize { get; } 33 /// <summary> 34 /// 已传输字节数 35 /// </summary> 36 long BytesTransferred { get; set; } 37 /// <summary> 38 /// 是否是异步传输 39 /// </summary> 40 bool IsAsyncTranse { get; } 41 /// <summary> 42 /// 传输方向 43 /// </summary> 44 DataTranseDirection DataTranseDirection { get; } 45 /// <summary> 46 /// 传输错误 47 /// </summary> 48 Exception TranseError { get; set; } 49 /// <summary> 50 /// 是否取消传输 51 /// </summary> 52 bool IsCancel { get; } 53 /// <summary> 54 /// 指示头传输是否已完成 55 /// </summary> 56 bool HeaderTransedOver { get; } 57 /// <summary> 58 /// 当DataTranseDirection=Connecting时使用 59 /// </summary> 60 EndPoint ConnectToEndPoint { get; } 61 /// <summary> 62 /// 当DataTranseDirection=Connecting时使用 63 /// 指示传输接口设置对象 64 /// </summary> 65 object ConnectTranseInterfaceSetting { get; } 66 /// <summary> 67 /// 头传输完成时调用 68 /// 该方法最低实现要将HeaderTransedOver设为True 69 /// </summary> 70 void HeaderTransed(); 71 /// <summary> 72 /// 异步传输完成时调用 73 /// </summary> 74 void AsyncTranseOver(); 75 /// <summary> 76 /// 异步传输进度通知 77 /// </summary> 78 void AsyncNotyTransing(); 79 } 80 81 /// <summary> 82 /// 数据传输头接口 83 /// </summary> 84 public interface ITranseHeader 85 { 86 /// <summary> 87 /// 传输的数据大小(不包含本头的大小)字节数 88 /// </summary> 89 long TranseSize { get; } 90 /// <summary> 91 /// 其它选项 92 /// </summary> 93 int TranseFlags { get; } 94 /// <summary> 95 /// 包含头的数据(不能为null),为一固定已知大小的字节数 96 /// 该数据包含了头的所有信息 97 /// </summary> 98 byte[] Data { get; } 99 /// <summary>100 /// 当Data属性的容发生变化时(如从网络接收完成Data数据内容时)101 /// 改变方会调用该方法以通知本体依据Data属性的内容重设头属性,如TranseSize和TranseFlags属性值102 /// </summary>103 void ResetParametsFromData();104 }105 106 public enum DataTranseDirection107 {108 /// <summary>109 /// 未知110 /// </summary>111 Unkown,112 /// <summary>113 /// 发送数据114 /// </summary>115 SendingData,116 /// <summary>117 /// 接收数据118 /// </summary>119 ReceivingData,120 /// <summary>121 /// 连接122 /// </summary>123 Connecting124 }125 126 public enum TranseInterfaceDirection127 {128 /// <summary>129 /// 客户端,表示是主动连接方130 /// </summary>131 Client,132 /// <summary>133 /// 服务端,表示是接受连接方134 /// </summary>135 Server136 }137 138 public interface ITranseInterfaceInformation139 {140 /// <summary>141 /// 获取本地终结点信息142 /// </summary>143 EndPoint LocalEndPont { get; }144 /// <summary>145 /// 获取远程终结点信息146 /// </summary>147 EndPoint RemoteEndPoint { get; }148 /// <summary>149 /// 获取当前传输接口建立连接时的方向150 /// </summary>151 TranseInterfaceDirection TranseDirection { get; }152 /// <summary>153 /// 获取传输协义名称154 /// </summary>155 string ProtocolTypeName { get; }156 }157 158 public interface ITranseInterfaceTranse159 {160 161 /// <summary>162 /// 数据传输或连接163 /// 发送或接收或连接:ITranseParamets.DataTranseDirection决定164 /// ITranseParamets.IsAsyncTranse决定是同步还是异步操作165 /// 对于异步操作ITranseParamets.AsyncTranseOver会在操作完成时调用166 /// 对于发送和接收操作ITranseParamets.HeaderTransed会在头发送或接收后调用167 /// </summary>168 /// <param name="transeparamets"></param>169 void TranseData(ITranseParamets transeparamets);170 171 /// <summary>172 /// 关闭传输接口173 /// </summary>174 void Close();175 176 /// <summary>177 /// 是否处于已连接状态178 /// </summary>179 bool IsConnected { get; }180 181 /// <summary>182 /// 等待对方关闭183 /// </summary>184 /// <param name="callback"></param>185 void WaitClose(object state, WaitCloseDelegate callback);186 }187 188 public delegate void WaitCloseDelegate(object state);189 190 191 public interface ITranseInterface : ITranseInterfaceTranse, ITranseInterfaceInformation192 {193 }194 195 public class TcpIPSocketSetting196 {197 198 static TcpIPSocketSetting()199 {200 DefaultLingerOption = new LingerOption(true, 30);201 }202 203 public TcpIPSocketSetting()204 {205 p_NoDelay = false;206 p_ReceiveBufferSize = 8192;207 p_SendBufferSize = 8192;208 p_ReceiveTimeout = 60000;209 p_SendTimeout = 10000;210 p_SocketLinger = null;211 }212 213 private static readonly LingerOption DefaultLingerOption;214 215 private bool p_NoDelay;216 217 public bool NoDelay218 {219 get { return p_NoDelay; }220 set { p_NoDelay = value; }221 }222 223 private int p_ReceiveBufferSize;224 225 public int ReceiveBufferSize226 {227 get { return p_ReceiveBufferSize; }228 set { p_ReceiveBufferSize = value; }229 }230 231 private int p_SendBufferSize;232 233 public int SendBufferSize234 {235 get { return p_SendBufferSize; }236 set { p_SendBufferSize = value; }237 }238 239 private int p_ReceiveTimeout;240 241 public int ReceiveTimeout242 {243 get { return p_ReceiveTimeout; }244 set { p_ReceiveTimeout = value; }245 }246 247 private int p_SendTimeout;248 249 public int SendTimeout250 {251 get { return p_SendTimeout; }252 set { p_SendTimeout = value; }253 }254 255 private LingerOption p_SocketLinger;256 257 public LingerOption SocketLinger258 {259 get260 {261 return p_SocketLinger == null ? DefaultLingerOption : p_SocketLinger;262 }263 set { p_SocketLinger = value; }264 }265 266 public void AppSetting(Socket s)267 {268 if (s != null)269 {270 if (SocketLinger != null)271 s.LingerState = SocketLinger;272 s.NoDelay = NoDelay;273 s.ReceiveBufferSize = ReceiveBufferSize;274 s.SendBufferSize = SendBufferSize;275 s.ReceiveTimeout = ReceiveTimeout;276 s.SendTimeout = SendTimeout;277 }278 }279 280 }281 282 }
来源:https://www.cnblogs.com/prnimeio/archive/2011/12/26/2302187.html