XmlSerializer不会通过NetworkStream反序列化

埃特·桑德维奇(IEatSandvich)

我正在寻求实现一个简单的客户端/服务器设置,该设置可以将序列化的EmailRequest对象(使用XmlSerializer)从客户端传输到服务器,以用于发送电子邮件。

服务器

class Program
{
    private static void Main()
    {
        try
        {
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8888);

            listener.Start();

            while (true)
            {
                Console.WriteLine("Waiting for request..");

                TcpClient client = listener.AcceptTcpClient();

                NetworkStream stream = client.GetStream();

                XmlSerializer serializer = new XmlSerializer(typeof(EmailRequest));

                EmailRequest request = (EmailRequest)serializer.Deserialize(stream); // This is where the problem is //

                bool success = SendGridUtility.SendEmail(request.Recipients, request.Subject,
                    request.BodyType == EmailRequest.Type.Plain ? request.PlainText : request.HTMLText,
                    request.BodyType).Result;

                byte[] response = Encoding.ASCII.GetBytes(success ? "Success" : "Failure");
                Console.WriteLine("Email Successfully Sent!");

                stream.Write(response, 0, response.Length);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Something went wrong.. :( :\n" + e.Message + "\n\n");
        }
        Console.ReadLine();
    }
}

客户

class Program
{
    static void Main(string[] args)
    {
        try
        {
            TcpClient client = new TcpClient("127.0.0.1", 8888);

            NetworkStream stream = client.GetStream();

            XmlSerializer serializer = new XmlSerializer(typeof(EmailRequest));

            EmailRequest request = new EmailRequest
            {
                BodyType = EmailRequest.Type.Plain,
                HTMLText = "not used",
                PlainText = "Email Body",
                Recipients = new List<string> {"[email protected]"},
                Subject = "Email Subject"
            };

            serializer.Serialize(stream,request);

            Byte[] data = new Byte[256];

            Int32 bytes = stream.Read(data, 0, data.Length);
            string responseData = Encoding.ASCII.GetString(data, 0, bytes);
            Console.WriteLine("Received: {0}", responseData);
            Console.ReadLine();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace + "\n\n");
            Console.WriteLine(e.Message);
            Console.ReadLine();
        }
    }
}

电子邮件请求模型

[Serializable]
public class EmailRequest
{
    public enum Type
    {
        Plain,
        HTML
    }
    public List<string> Recipients { get; set; }
    public string Subject { get; set; }
    public Type BodyType { get; set; }
    public string PlainText { get; set; }
    public string HTMLText { get; set; }
}

当程序到达该Deserialize方法时,应用程序不会挂起,而是等待,好像它正在等待用户输入一样,我也不知道为什么。除了我今天所做的之外,我还没有TCP / XmlSerialization / Streams的经验。与往常一样,有关如何改进程序的任何帮助或建议将不胜感激。谢谢。

彼得·杜尼奥(Peter Duniho)

这里的问题是XmlSerializer,由于客户端无法关闭套接字,因此无法知道没有更多数据要反序列化。

调用之后serializer.Serialize(stream,request);,您需要添加以下代码行:

client.Client.Shutdown(SocketShutdown.Send);

这将指示来自客户端的流结束,以便服务器知道数据传输已完成。这样,用户就XmlSerializer可以知道没有其他尝试反序列化的方法,并且它可以返回新对象。

此外,服务器从不调用Shutdown()任何一个。您可以通过发布的代码来解决它,因为您的客户端在接收时不会检查流的末尾。

尽管这可能几乎在所有时间都有效,但这不是很正确。由于您不检查接收值的长度,因此您无法知道客户端已接收到服务器已发送的所有数据作为响应。

相反,您应该首先将服务器固定为call Shutdown(),方法是在将响应写入流之后添加以下语句:

client.Client.Shutdown(SocketShutdown.Both);
client.Close();

然后,您还需要修复客户端…

客户端处理响应的一种更简单,更可靠的方法是使用以下命令替换所有内容Shutdown()

using (StreamReader reader = new StreamReader(stream))
{
    string line;

    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine("Received: " + line);
    }
}

这使您不必担心底层的流I / O,而将其委托给StreamReader类,该类可以以更方便的方式处理数据(即,它自动缓冲数据并正确检测流的结束)。

最后,在收到剩余数据(按上述方法)之后,您还应该关闭客户端套接字:

client.Close();

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

JMS反序列化多对多关系不会通过orphanremoval删除

XmlSerializer不反序列化DateTime

JSONObject反序列化不会反序列化

如何通过使用WCF SoapClient在反序列化(XmlSerializer)上忽略UnknownElements?

如何使用XmlSerializer解析反序列化的属性(反序列化期间)?

XmlSerializer:反序列化递归对象图

使用XmlSerializer反序列化XML的替代方法

使用XmlSerializer反序列化嵌套列表

不带名称空间的XmlSerializer反序列化列表

gson不会反序列化数组

Json String不会反序列化

持久实体不会反序列化

GoCardless事件不会反序列化

Unity,JsonFX不会反序列化

我序列化/反序列化的项目越多,BinaryFormatter就会比XmlSerializer慢

XMLSerializer正确序列化,但是在反序列化时抛出TargetInvocationException

XmlSerializer:反序列化为XMLElement

在 C# 中反序列化 (.net json) 或序列化 (XmlSerializer) 期间填充 NULL 值

protobuf不会正确反序列化对象

@RequestBody对象不会自动反序列化

WebService不会反序列化某些对象

JSON.NET 反序列化不会触发 setter

ServiceStack 5.1.0不会反序列化对象字段

ProtoBuf不会使用接口反序列化对象

JsonNetValueProviderFactory不会从AngularJS帖子中反序列化JSON

C#中的XmlSerializer,通过特定属性反序列化用多个同名XmlElement装饰的类?

Apaches Ignite不会序列化/反序列化Guavas LoadingCache

如何使用XmlSerializer将异构子节点反序列化到集合中?

反序列化派生类时出现XmlSerializer异常(不应预期<Derived xmlns =''>)