.NET Framework Bookmark and Share   
 index > .NET Remoting and Runtime Serialization > Serializing with TCP
 

Serializing with TCP

I've got a routine that sends a serialized file using TCP from a Client to our Server.

If the serialized files are small, text only files under 8 KB (= TCP's BufferSize), the files are transferred without any problems.

If the serialized files are larger (generally because we are trying to send an image across), my routine will fail because the connection on the Server will be forced closed.

I'd like someone to guide me on how to keep this connection open so that the entire message can be received.

Below is the Client Code snippet:

// this does all of the work for sending
int sendUsingTcp(string location) {
  _result = string.Empty;
  try {
    using (FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read)) {
      using (TcpClient client = new TcpClient(GetHostIP, AcpClasses.CpAppDatabase.ServerPortNumber)) {
        byte[] buf = new byte[client.SendBufferSize];
        using (NetworkStream ns = client.GetStream()) {
          if ((ns.CanRead == true) && (ns.CanWrite == true)) {
            byte[] bufInfo = Encoding.UTF8.GetBytes(fs.Length.ToString());
            ns.Write(bufInfo, 0, bufInfo.Length); // tells the Server how much data I am about to send
            Thread.Sleep(1000); // give data time to get there and be processed
            int len;
            do {
              len = fs.Read(buf, 0, buf.Length);
              ns.Write(buf, 0, len);
            } while (len == buf.Length);
            len = ns.Read(buf, 0, buf.Length);
            _result = Encoding.UTF8.GetString(buf, 0, len);
            return 1;
          }
          return 0;
        }
      }
    }
  } catch (Exception err) {
    Logger.LogError("Send()", err);
    _result = err.Message;
    return -1;
  }
}
Notice that I start by sending the length of the data transfer, give the Server a second to process this, then send my actual message.

The Server's response is recorded tothe modularly global string variable _result.

Meanwhile, here is what is running 24/7 on the Server:
public static TcpListener Listener;

void Worker_Engine(object sender, DoWorkEventArgs e) {
  BackgroundWorker worker = sender as BackgroundWorker;
  DateTime noDate = new DateTime(1900, 1, 1);
  DateTime started = noDate;
  string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.CompanyName);
  if (Directory.Exists(path) == false) Directory.CreateDirectory(path);
  int length2 = 0;
  string location = string.Empty;
  Thread.Sleep(0);
  string eMsg = string.Empty;
  FileStream stream = null;
  try {
    Listener.Start();
    do {
      using (TcpClient client = Listener.AcceptTcpClient()) { // waits until data is avaiable
        if (worker.CancellationPending == true) return;
        client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
        byte[] buf = new byte[client.ReceiveBufferSize];
        using (NetworkStream ns = client.GetStream()) {
          try {
            if (stream == null) {
              started = DateTime.Now;
              location = Path.Combine(path, string.Format("Acp{0:yyyyMMddHHmmssff}.bin", started));
              stream = new FileStream(location, FileMode.Create, FileAccess.Write);
              length2 = 0;
            }
            int len = ns.Read(buf, 0, client.ReceiveBufferSize);
            bool next = false;
            if (length2 == 0) {
              string line = Encoding.UTF8.GetString(buf, 0, len);
              if (Global.IsNumeric(line) == true) { // this is the new format
                length2 = Global.ToInt32(line);
                next = (0 < length2);
              }
            }
            if (next == false) {
              stream.Write(buf, 0, len);
              TimeSpan span = (DateTime.Now - started);
              if (((len < client.ReceiveBufferSize) && (length2 == 0)) // Override Message
                || (length2 == stream.Length) || (5 < span.Minutes)) {
                try {
                  stream.Flush();
                  stream.Close();
                  worker.ReportProgress(1, location);
                  byte[] okBuf = Encoding.UTF8.GetBytes("Message Received on Server");
                  ns.Write(okBuf, 0, okBuf.Length);
                } finally {
                  stream.Dispose();
                  stream = null;
                }
              }
            }
          } catch (Exception err) {
            Global.LogError("ServerForm.cs - Worker_Engine(DoWorkEvent)", err);
            byte[] errBuf = Encoding.UTF8.GetBytes(err.Message);
            ns.Write(errBuf, 0, errBuf.Length);
          }
        }
      }
    } while (worker.CancellationPending == false);
  } catch (Exception err) {
    Console.WriteLine("Worker General Error:\r\n" + err.Message);
    e.Cancel = true;
  } finally {
    if (stream != null) {
      stream.Flush();
      stream.Close();
      stream.Dispose();
      stream = null;
    }
    Listener.Stop();
  }
}<br/>

The first line read from the Server tries tocollect the length of data that will be coming in. We may still have some legacy systems that do not send the data length first. If the first data read is not a length, it is a short message that is immediately processed. If it is a length, the connection collects until one of two things occurs: 1) The length is reached, or 2) 5 minutes pass - at which time it gives up.

When longer messages are sent through the Server, though, the response received by the client is that the connection was forcibly closed by the host.

Our Network Administrator does not know how to resolve this. His response was, "It's your program. You figure it out." (sigh)

Being a Server, he says the firewall must be turned off, so that can't be it.

What could be causing the Server to kill this connection?

I tried running both apps on my PC to debug, but it can't open the same port for the Client and the Server (obviously), so it is hard to debug what is going on from the Server.

Any ideas?

jp2msft
I'd just like to point out that it should be possible to run both the client and the server code on the same machine. I'vedone a lot ofC#TCP/IP development and have always done the development and testing on one PC. I run two copies of Visual Studio andoccasionally evenrun both programs under the debugger at the same time, although more typically I'm running one program under the VS debugger and the other as a regular program.

As for allocation of network ports, it's normally only the server programthat allocates a fixed port, so that should not result in a conflict. The server program allocatesthe fixed port and listens for connections.The client connects to "localhost" and the server's fixed port without specifying any port for its own use - that is allocated dynamically and may well have a different number every time.

Hope this helps.

Rennie
RennieP
If your Client and server are diff m/c then you have to open the specific port on which your server object is running in firewall on server.
I hope then ur problem will resolve.

All the best :-)
gaurav83
Client and Server are on different machines, both specify the same port number, and the Server does not run a firewall - because it is a Server!

Again, anything under 8 KB will transfer without any problem. If I try to send images across, the first 8 KB goes through, but then the network connection is closed by the Server. That I can tell, my code does not tell the Server to close the connection.

Still open to ideas, as this problem has not been resolved.

Avoid Sears Home Improvement
jp2msft
As for allocation of network ports, it's normally only the server programthat allocates a fixed port, so that should not result in a conflict. The server program allocatesthe fixed port and listens for connections.The client connects to "localhost" and the server's fixed port without specifying any port for its own use - that is allocated dynamically and may well have a different number every time.
I am a little confused by that first sentence. Perhaps there was a typo in there somewhere.

Do your TCP/IP applications ever try to send anything over 8 KB, like if you wanted to use TCP to send a file to the Server?

I would be very interested in seeing how this is done - obviously, my code does something wrong.

Avoid Sears Home Improvement
jp2msft

You can use google to search for other answers

Custom Search

More Threads

• Class serialization problem (with an Assembly as one of the members of the class)
• Fail to serialize object of control by Dot Net XMLSerializer -- Form.Site member is an interface.
• Remoting Question
• Issue with events
• IPC and serialization
• Binary Serialization and byte value of 255
• How do I get .net remoting to work securely with C# and 64 bit Vista code?
• Channel creation problem in C# Express
• Re: Server Error in '/' Application.
• Remoting: exception when the server is off