Hello, wrote some client-server application in which: 1) The client sends a request (I just send "SELECT" in this example) 2) The server in response to this sends some xml serialization of an object of the Person class (in the future, I will be with EntityFramework -a (bd) pull out a range of objects on request and transfer them to the client (for now it does not matter). Server code:

class Program { private static Socket server = new Socket(AddressFamily.InterNetworkV6,SocketType.Stream,ProtocolType.Tcp); // private static List<Socket> clients; private static List<Person> persons = new List<Person>() { new Person(0,18,"Sergey 1111"), new Person(1,30,"1111 Maksim"), new Person(2,20,"Pasha 1111"), new Person(3,27,"4444 Ivanov") }; static void Main(string[] args) { StartServer(); Console.ReadLine(); } public static void StartServer() { try { IPEndPoint end = new IPEndPoint(IPAddress.Parse("***::***:***:***:***%***"), 8005); server.Bind(end); server.Listen(10); Console.WriteLine("> server {0} has started", end); server.BeginAccept(AcceptCallback,null); } catch (Exception ex) { Console.WriteLine(ex.Message); } } public static void AcceptCallback(IAsyncResult ar) { Socket client = server.EndAccept(ar); Thread thread = new Thread(HandleClient); thread.Start(client); server.BeginAccept(AcceptCallback, null); } public static void HandleClient(object o) { try { Socket client = (Socket)o; byte[] buffer = new byte[256]; MemoryStream ms = new MemoryStream(new byte[256], 0, 256, true, true); BinaryReader reader = new BinaryReader(ms); BinaryWriter writer = new BinaryWriter(ms); while (true) { ms.ClearMemory(); client.Receive(ms.GetBuffer()); string cmd = reader.ReadString(); Console.WriteLine("> {0}", cmd); ms.ClearMemory(); switch (cmd) { case "SELECT": { SendQueryResult(client); break; } }; writer.Write("server> Message sent"); client.Send(ms.GetBuffer()); } }catch(Exception ex) { Console.WriteLine(ex.Message); } } public static void SendQueryResult(object o) { List<string> query_result = new List<string>(); Socket client = (Socket)o; MemoryStream ms = new MemoryStream(new byte[512], 0, 512, true, true); BinaryReader reader = new BinaryReader(ms); BinaryWriter writer = new BinaryWriter(ms); ms.ClearMemory(); foreach(Person p in persons) { query_result.Add(p.Serialize()); } foreach(string xml in query_result) { ms.ClearMemory(); writer.Write(xml); client.Send(ms.GetBuffer()); } } public static bool SocketConnected(Socket s) { bool part1 = s.Poll(1000, SelectMode.SelectRead); bool part2 = (s.Available == 0); if (part1 && part2) return false; else return true; } } public static class EMethods { public static void ClearMemory(this MemoryStream stream) { Array.Clear(stream.GetBuffer(), 0, stream.GetBuffer().Length); stream.Position = 0; } public static string Serialize<T>(this T value) { if (value == null) { return string.Empty; } try { var xmlserializer = new XmlSerializer(typeof(T)); var stringWriter = new StringWriter(); using (var writer = System.Xml.XmlWriter.Create(stringWriter)) { xmlserializer.Serialize(writer, value); return stringWriter.ToString(); } } catch (Exception ex) { throw new Exception("An error occurred", ex); } } } 

Client code:

 class Program { private static string querydata = "EMPTY"; private static List<XmlDocument> xml_results = new List<XmlDocument>(); private static Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); private static MemoryStream ms = new MemoryStream(new byte[256], 0, 256, true, true); private static BinaryWriter writer = new BinaryWriter(ms); private static BinaryReader reader = new BinaryReader(ms); static void Main(string[] args) { IPEndPoint IPend = new IPEndPoint(IPAddress.Parse(""***::***:***:***:***%***""), 8005); socket.Connect(IPend); Console.WriteLine("> successfully connected to {0}", IPend); while (true) { Console.Write("cmd> "); string cmd = Console.ReadLine(); //MemoryStream m_stream = new MemoryStream(buffer); // BinaryWriter b_writer = new BinaryWriter(m_stream); switch (cmd) { case "exit": { return; } case "select": { querydata = "SELECT"; break; } case "create": { querydata = "CREATE"; break; } case "update": { querydata = "UPDATE"; break; } case "delete": { querydata = "DELETE"; break; } }; List<string> query_result = new List<string>(); SendPacket(querydata); while(true) { string result = ReceivePacket(); if(result == "server> Result sent" || result == "server> Message sent") { break; } else { query_result.Add(result); } } foreach(var xml_str in query_result) { XmlDocument document = new XmlDocument(); document.LoadXml(xml_str); xml_results.Add(document); } ViewXMLResult(xml_results); xml_results.Clear(); query_result.Clear(); } } public static void ViewXMLResult(List<XmlDocument> list) { foreach(var doc in list) { XmlElement elem = doc.DocumentElement; XmlNode node = elem.SelectSingleNode("PersonID"); XmlNode node1 = elem.SelectSingleNode("Age"); XmlNode node2 = elem.SelectSingleNode("FullName"); Console.WriteLine("Xml ID = {0} \nXml Age = {1} \nXml FullName = {2}", node.InnerText, node1.InnerText, node2.InnerText); Console.WriteLine(); } } public static void ConnectToServer(Socket sock, IPEndPoint end) { try { sock.Connect(end); Console.WriteLine("> successfully connected to {0}", end); } catch (Exception ex) { Console.WriteLine(ex); } } public static void SendPacket(string data) { ms.ClearMemory(); writer.Write(data); socket.Send(ms.GetBuffer()); } public static string ReceivePacket() { ms.ClearMemory(); socket.Receive(ms.GetBuffer()); string message = reader.ReadString(); Console.WriteLine(message); return message; } } public static class EMethods { public static void ClearMemory(this MemoryStream stream) { Array.Clear(stream.GetBuffer(), 0, stream.GetBuffer().Length); stream.Position = 0; } } 

I'm having some problem getting data to the client. On the server, I calmly get a list of serialized objects (as a string in which xml) and pass them to the client. On the client, I get all the data, but in addition, between the transferred data, the client receives an empty string. That is, the 1st xml string I get everything on the client is ok, for some reason the client then gets a “” (empty string) and then gets a normal object. Roughly speaking, the result on the client is obtained in this form 1) xml1 2) "" 3) xml2 4) "" 5) xml3 6) "" 7) xml4. That is, I’m getting all 4x xml, but I’m also getting blank lines, what time I’m sitting I can’t find my mistake, can anyone see the empty line that I am passing?

    1 answer 1

    Most likely in this way a newline is serialized. You need to make settings like this:

     XmlWriterSettings settings = new XmlWriterSettings(); settings.NewLineHandling = NewLineHandling.None; 
    • The fact is that after serialization in the list of xml strings, there is nothing like a line break. It turns out I send 4 lines from the sheet (that is, I send 4 times, at this time the client must take 4 times, and for some reason it takes 3 additional times. I set a delay of half a second in the cycle of receiving data from the server, the same result. In In general, I have not tried your method yet, but in theory nothing will happen, since there are no spaces \ line break characters there - Sergey Ivanyuk
    • In general, it only comes to my mind to make a crutch that processes the output list and removes all empty lines. It seems that the server after sending the line re-sends an empty string, that is, an empty buffer, but I can’t normally preempt it, too noob. - Sergey Ivanyuk
    • Found a problem. It is on the client. When sending to the server, the Send method sends 4 times, and the Receive method on the client accepts 8 times. (3 empty straki + message about the end of sending). You have to think about how best to synchronize the sending and receiving of data - Sergey Ivanyuk
    • In general, the problem is in the cycle in which I start receiving all objects separately. The client asks for the data too quickly and receives a blank line. Although if it were a matter of speed, then Thread.Sleep () would help, but it does not help. I will think further - Sergey Ivanyuk
    • Friendly advice: If your project is going to develop, then it is better to immediately abandon your own implementation of sockets, and use WCF - Ivan K