public RPC(string ip, int port) { IPAddress ipAddress = IPAddress.Parse(ip); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port); this.socketPool = SocketPool.GetPool(ipEndPoint); }
public static SocketPool GetPool(IPEndPoint ipEndPoint) { SocketPool pool; lock (_dic) { if (_dic.TryGetValue(ipEndPoint, out pool)) { return(pool); } pool = new SocketPool(ipEndPoint); _dic.Add(ipEndPoint, pool); } return(pool); }
public void Send(ref Socket s, SMessage m, SocketPool socketPool) { byte[] head = GetBytes(m); if (head.Length > headSize) { throw new RPCException("Head 的 长度不能超过 " + headSize + " Byte , 注意 Header 值会进行 Url Encode , 中文字符经过 Url Encode 之后会变长 。"); } // 如果 socketPool != null 表示是 客户端 在调用 Send() 方法 , 发生异常时需要创建新的 Socket 重新 Send() // 反之 , 则表示是 服务器端 在调用 Send() 方法 , 不需要重新 Send() if (socketPool != null) { // 这里的 try catch 是为了解决 服务器关闭连接 后 客户端 不知道 服务器连接 已关闭 的问题。 // 客户端仍然从 SocketPool 中取出之前的 Socket 来使用 , 但因为服务器连接已经关闭, // 所以这个 Socket 是不能使用的,用了会报错,所以,这里在 catch 里会关闭已失效的 Socket , // 并且新创建一个 Socket ,和 服务器建立新的连接,用新的 Socket 来 Send() , // 返回到 RPC.Send() 方法后 , 这个新的 Socket 会被 Return 到 SocketPool 。 // 所以这里的 Socket s 参数是 ref 参数 。 就是为了将 新的 Socket 返回到 RPC.Send() 方法 。 // 正常来讲,服务器不会主动关闭连接,但在一些意外情况,比如服务器意外关闭时,服务器连接会意外关闭 。 try { s.Send(head); } catch { socketPool.Close(s); // 这里要特别先把 s = null; 是因为如果在 SocketPool.GetNew() 中出现异常, // 没有成功的创建 新 Socket 赋值给 s , 则返回 RPC.Send() 方法后,会在 catch 中去关闭 s , // 但这个时候的 s 是在上面已经被关闭的 s ,于是会报“无法访问已释放的对象”的错误 。 s = null; s = socketPool.GetNew(); s.Send(head); } } else { s.Send(head); } if (m.Content == null) { return; } byte[] b; int bufferSize; int sendCount; int readCount; long totalSendCount = 0; while (true) { bufferSize = totalSendCount + sendContentBufferSize <= m.ContentLength ? sendContentBufferSize : (int)(m.ContentLength - totalSendCount); b = new byte[bufferSize]; readCount = m.Content.Read(b, 0, bufferSize); sendCount = s.Send(b, 0, readCount, SocketFlags.None); totalSendCount += sendCount; if (totalSendCount >= m.ContentLength) { break; } } // 如果 Send 的 Content 长度未达到 Content-Length 指定的长度 , 则发送 空字符 \0 来补齐 // 直到达到 Content-Length 的长度 long vacancyLength = m.ContentLength - totalSendCount; if (vacancyLength > 0) { SendVacancy(s, vacancyLength); } }