Beispiel #1
0
        private byte[] GetBytes(SMessage m)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("Parameters: ");

            Para   p;
            string name;
            string value;

            for (int i = 0; i < m.Parameters.Count; i++)
            {
                p = m.Parameters[i];

                name  = HttpUtility.UrlEncode(p.name);
                value = HttpUtility.UrlEncode(p.value);

                sb.Append(name + "=" + value + "&");
            }

            sb.Append("\r\n");

            if (m.Error != null)
            {
                sb.Append("Error: " + HttpUtility.UrlEncode(m.Error));
                sb.Append("\r\n");
            }

            if (m.Content != null)
            {
                if (m.ContentLength <= 0)
                {
                    throw new RPCException("设置了 Content 属性的情况下 ContentLength 应大于 0 。");
                }

                sb.Append("Content-Length: " + m.ContentLength);

                sb.Append("\r\n");
            }

            sb.Append("\r\n");

            string head = sb.ToString();

            return(Encoding.ASCII.GetBytes(head));
        }
Beispiel #2
0
        public RMessage Send(SMessage m)
        {
            Socket clientSocket = null;

            RMessage rMsg;

            try
            {
                clientSocket = this.socketPool.Get();

                MessageParser mp = new MessageParser();

                mp.Send(ref clientSocket, m, this.socketPool);

                rMsg = mp.Parse(clientSocket);

                this.socketPool.Return(clientSocket);
            }
            catch
            {
                if (clientSocket != null)
                {
                    this.socketPool.Close(clientSocket);
                }

                throw;
            }


            if (rMsg.Error != null)
            {
                throw new RPCServerException(rMsg.Error);
            }

            return(rMsg);
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        private void Receive(object clientSocket)
        {
            Socket s = (Socket)clientSocket;

            MessageParser mp = new MessageParser();

            RMessage m;

            SMessage sMsg;

            SMessage errorMsg;

            Exception error;

            while (true)
            {
                try
                {
                    m        = null;
                    sMsg     = null;
                    errorMsg = null;
                    error    = null;



                    m = mp.Parse(s);


                    try
                    {
                        sMsg = OnMessageArrived(m);
                    }
                    catch (Exception e)
                    {
                        error = e;
                    }

                    //  如果 在 OnMessageArrived 中没有读取完 m.Content ,则需要继续读完 ,
                    //  否则没有读完的内容会被当成下一次 Request 的 Head , 导致请求错误 。
                    if (m.Content != null)
                    {
                        mp.ReadToEnd(m.Content);
                    }

                    if (error != null)
                    {
                        errorMsg       = new SMessage();
                        errorMsg.Error = error.Message;

                        mp.Send(ref s, errorMsg, null);
                    }
                    else
                    {
                        mp.Send(ref s, sMsg, null);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " " + ex.ToString());
                    s.Shutdown(SocketShutdown.Both);
                    s.Close();
                    break;
                }
            }
        }