none
网络上的数据如何转换和传输? RRS feed

  • 问题

  • 如果我已构造一个针对Winform表单提交数据的数据类容器文件employee.cs,通过和Winform表单文件一起被编译后向服务器端提交数据并存入数据库中。但我不知道这个数据(严格来说应该是字数组)是如何提交到服务器,服务器又是如何工作实现把接收到的数据有序地存入数据库指定的表当中的?是不是每个客户端都应该有一个对应地服务器文件进行工作?
    在数据序列化方案中好象有两种:BinaryFormatter,SoapFormatter,并且采用TCP信道+BinaryFormatter模式进行网络数据传输效果是最优的,这种说法对吗?
    我的employee.cs文件大致如下:
    .....................
    class employee
    {
       public int employeeID;
       private int nameSize;
       public string name;
       public int yearsService;
       public int salary;
       public int size;
    }
    public employee()
    {
    }
    public employee(byte[] data)
    {
       int place=0;
       empolyeeID=bitconverter.int32(data,place);
       place+=4;
       nameSize=bitconverter.int32(data,place);
       place+=4;
       name=Encoding.ASCII.getstring(data,place,nameSize);
       place=place+nameSize;
       yearsService=bitconverter.int32(data,place);
       place+=4;
       salary=bitconverter.ToDouble(data,place);  
    }
    public byte[] getbytes()
    {
       byte[] data=new byte[1024];
       int place=0;
       Buffer.BlockCopy(bitconerter.getbytes(EmployeeID),0,data,place,4);
       place+=4;
       ............(省略)
       return data;
    }
    ...................
    • 已移动 Sheng Jiang 蒋晟Moderator 2009年3月25日 20:39 .Net基础类库问题 (从 Visual C# 移动到 .NET Framework 一般性问题讨论区)
    2009年3月25日 1:30

答案

  • 你好!
          BinaryFormatter:将对象分解成为简单的二进制格式,这种类型的序列化并不会遗失原来的类型数据,对象使用二进制序列化分解之后,可以被传送至各种存储 媒介,包括数据流,磁盘,内存甚至网络上连接的主机。
          SoapFormatter:将对象分解成为XML格式,使用SOAP标准来访问,由于XML与SOAP是开放标准,因此特别适用于对象需要跨越网络传送的情形, 与二进制序列化不同的是,使用这种格式的序列化,只会序列化分解类型中的公用(Public)属性和字段等内容。
          性能上来说BinaryFormatter更好写,而且会序列化所有成员,而SoapFormatter只序列化公有成员。但是SoapFormatter使用开发标准,可移植性更好些!

    周雪峰
    2009年3月25日 6:05
    版主
  • 你需要写一个客户端和一个服务端程序,只要使用TcpListener类和TcpClient类
    服务端代码:
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;

    class MyTcpListener
    {
    public static void Main()
    {
    TcpListener server=null;
    try
    {
    // Set the TcpListener on port 13000.
    Int32 port = 13000;
    IPAddress localAddr = IPAddress.Parse("127.0.0.1");

    // TcpListener server = new TcpListener(port);
    server = new TcpListener(localAddr, port);

    // Start listening for client requests.
    server.Start();

    // Buffer for reading data
    Byte[] bytes = new Byte[256];
    String data = null;

    // Enter the listening loop.
    while(true)
    {
    Console.Write("Waiting for a connection... ");

    // Perform a blocking call to accept requests.
    // You could also user server.AcceptSocket() here.
    TcpClient client = server.AcceptTcpClient();
    Console.WriteLine("Connected!");

    data = null;

    // Get a stream object for reading and writing
    NetworkStream stream = client.GetStream();

    int i;

    // Loop to receive all the data sent by the client.
    while((i = stream.Read(bytes, 0, bytes.Length))!=0)
    {
    // Translate data bytes to a ASCII string.
    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
    Console.WriteLine("Received: {0}", data);

    // Process the data sent by the client.
    data = data.ToUpper();

    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

    // Send back a response.
    stream.Write(msg, 0, msg.Length);
    Console.WriteLine("Sent: {0}", data);
    }

    // Shutdown and end connection
    client.Close();
    }
    }
    catch(SocketException e)
    {
    Console.WriteLine("SocketException: {0}", e);
    }
    finally
    {
    // Stop listening for new clients.
    server.Stop();
    }


    Console.WriteLine("\nHit enter to continue...");
    Console.Read();
    }
    }
    客户端代码:
    static void Connect(String server, String message) 
    {
    try
    {
    // Create a TcpClient.
    // Note, for this client to work you need to have a TcpServer
    // connected to the same address as specified by the server, port
    // combination.
    Int32 port = 13000;
    TcpClient client = new TcpClient(server, port);

    // Translate the passed message into ASCII and store it as a Byte array.
    Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

    // Get a client stream for reading and writing.
    // Stream stream = client.GetStream();

    NetworkStream stream = client.GetStream();

    // Send the message to the connected TcpServer.
    stream.Write(data, 0, data.Length);

    Console.WriteLine("Sent: {0}", message);

    // Receive the TcpServer.response.

    // Buffer to store the response bytes.
    data = new Byte[256];

    // String to store the response ASCII representation.
    String responseData = String.Empty;

    // Read the first batch of the TcpServer response bytes.
    Int32 bytes = stream.Read(data, 0, data.Length);
    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
    Console.WriteLine("Received: {0}", responseData);

    // Close everything.
    stream.Close();
    client.Close();
    }
    catch (ArgumentNullException e)
    {
    Console.WriteLine("ArgumentNullException: {0}", e);
    }
    catch (SocketException e)
    {
    Console.WriteLine("SocketException: {0}", e);
    }

    Console.WriteLine("\n Press Enter to continue...");
    Console.Read();
    }



    周雪峰
    2009年3月26日 6:54
    版主
  • 如果是这样的话,你自己定义一个类,把你要传递的各个字段定义为这个类的属性,在客户端把这个类序列化到NetStream,在服务端反序列化就获取这些值了! 
    周雪峰
    2009年3月27日 5:07
    版主

全部回复

  • 你好!
          BinaryFormatter:将对象分解成为简单的二进制格式,这种类型的序列化并不会遗失原来的类型数据,对象使用二进制序列化分解之后,可以被传送至各种存储 媒介,包括数据流,磁盘,内存甚至网络上连接的主机。
          SoapFormatter:将对象分解成为XML格式,使用SOAP标准来访问,由于XML与SOAP是开放标准,因此特别适用于对象需要跨越网络传送的情形, 与二进制序列化不同的是,使用这种格式的序列化,只会序列化分解类型中的公用(Public)属性和字段等内容。
          性能上来说BinaryFormatter更好写,而且会序列化所有成员,而SoapFormatter只序列化公有成员。但是SoapFormatter使用开发标准,可移植性更好些!

    周雪峰
    2009年3月25日 6:05
    版主
  • 恩,这个可以的
    2009年3月25日 12:25
  •  但我不知道这个数据(严格来说应该是字数组)是如何提交到服务器,服务器又是如何工作实现把接收到的数据有序地存入数据库指定的表当中的?是不是每个客户端都应该有一个对应地服务器文件进行工作?
    2009年3月26日 3:58
  • 你需要写一个客户端和一个服务端程序,只要使用TcpListener类和TcpClient类
    服务端代码:
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;

    class MyTcpListener
    {
    public static void Main()
    {
    TcpListener server=null;
    try
    {
    // Set the TcpListener on port 13000.
    Int32 port = 13000;
    IPAddress localAddr = IPAddress.Parse("127.0.0.1");

    // TcpListener server = new TcpListener(port);
    server = new TcpListener(localAddr, port);

    // Start listening for client requests.
    server.Start();

    // Buffer for reading data
    Byte[] bytes = new Byte[256];
    String data = null;

    // Enter the listening loop.
    while(true)
    {
    Console.Write("Waiting for a connection... ");

    // Perform a blocking call to accept requests.
    // You could also user server.AcceptSocket() here.
    TcpClient client = server.AcceptTcpClient();
    Console.WriteLine("Connected!");

    data = null;

    // Get a stream object for reading and writing
    NetworkStream stream = client.GetStream();

    int i;

    // Loop to receive all the data sent by the client.
    while((i = stream.Read(bytes, 0, bytes.Length))!=0)
    {
    // Translate data bytes to a ASCII string.
    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
    Console.WriteLine("Received: {0}", data);

    // Process the data sent by the client.
    data = data.ToUpper();

    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

    // Send back a response.
    stream.Write(msg, 0, msg.Length);
    Console.WriteLine("Sent: {0}", data);
    }

    // Shutdown and end connection
    client.Close();
    }
    }
    catch(SocketException e)
    {
    Console.WriteLine("SocketException: {0}", e);
    }
    finally
    {
    // Stop listening for new clients.
    server.Stop();
    }


    Console.WriteLine("\nHit enter to continue...");
    Console.Read();
    }
    }
    客户端代码:
    static void Connect(String server, String message) 
    {
    try
    {
    // Create a TcpClient.
    // Note, for this client to work you need to have a TcpServer
    // connected to the same address as specified by the server, port
    // combination.
    Int32 port = 13000;
    TcpClient client = new TcpClient(server, port);

    // Translate the passed message into ASCII and store it as a Byte array.
    Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

    // Get a client stream for reading and writing.
    // Stream stream = client.GetStream();

    NetworkStream stream = client.GetStream();

    // Send the message to the connected TcpServer.
    stream.Write(data, 0, data.Length);

    Console.WriteLine("Sent: {0}", message);

    // Receive the TcpServer.response.

    // Buffer to store the response bytes.
    data = new Byte[256];

    // String to store the response ASCII representation.
    String responseData = String.Empty;

    // Read the first batch of the TcpServer response bytes.
    Int32 bytes = stream.Read(data, 0, data.Length);
    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
    Console.WriteLine("Received: {0}", responseData);

    // Close everything.
    stream.Close();
    client.Close();
    }
    catch (ArgumentNullException e)
    {
    Console.WriteLine("ArgumentNullException: {0}", e);
    }
    catch (SocketException e)
    {
    Console.WriteLine("SocketException: {0}", e);
    }

    Console.WriteLine("\n Press Enter to continue...");
    Console.Read();
    }



    周雪峰
    2009年3月26日 6:54
    版主
  • 你这写的是一个C/s的控制台应用程序格式,我是问如果我用的是winforms写的客户端,并且该客户端上许多文本框控件当中是我需要提交的表单数据,对应的服务器端程序是如何把这些从客户端提交的(多个文本框中提交的)数据存入数据库的?我之前一直想不明白,这些利用networkstream一次传输到服务程序的数据是怎么有序地存入到数据库表对应地字段当中的?而不是把这些networkstream流数据一下子全部都存到表中的一个字段里?
    2009年3月27日 1:04
  • 如果是这样的话,你自己定义一个类,把你要传递的各个字段定义为这个类的属性,在客户端把这个类序列化到NetStream,在服务端反序列化就获取这些值了! 
    周雪峰
    2009年3月27日 5:07
    版主