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?