У меня есть приложение, которое я написал для своего приложения, распространяемого по всей компании, для отправки данных мне через наш сервер Windows 2003 (с запуском IIS 6.0). Небольшие текстовые сообщения проходят, но большие сообщения, содержащие больше данных (около 20 КБ), не проходят.TCP-соединение с клиентом
Я установил байтовый буфер в размер буфера TCP-клиента. Я заметил, что мои данные поступают на сервер; однако он только зациклился на процедуру приема один раз, и мои большие файлы всегда были точно размером с размером буфера, или 8 КБ на нашем сервере. Другими словами, мой код пропускает только один цикл до того, как сервер закроет соединение сокета.
Думаю, что может возникнуть проблема с заполнением всего буфера, я попытался ограничить чтение/запись всего на 1 КБ, но это привело только к тому, что наш сервер закрыл сокет после получения 1 КБ до закрытия соединения.
Я отправляю сообщение об ошибке сервера клиенту, чтобы я мог его просмотреть. Конкретное сообщение об ошибке, что я получаю от клиента:
“Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.”
Я обновил свое серверное приложение так, что лежащий в основе сокет TCP будет использовать «держать alives» с этой линией:
client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
Теперь, когда Я попытка отправки сообщения, клиент получает сообщение об ошибке:
“Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.”
наш администратор сети сказал мне, что он не имеет брандмауэр или какие-либо порты заблокированы на нашем внутреннем сервере.
Исправлены ошибки, я нашел сообщения, предлагающие людям пытаться подключиться к серверу telnet. Я использовал их направления для телнета на сервер, но я не уверен, что сделать из ответа:
C:> telnet Welcome to Microsoft Telnet Client
Escape Character is ‘CTRL+]’
Microsoft Telnet> open cpapp 500 Connecting To cpapp…
Это все я. Я никогда не получаю сообщение об ошибке, и экран Telnet от Microsoft в конечном итоге изменится на «Нажмите любую клавишу, чтобы продолжить ...» - я думаю, это время, но мой код каким-то образом может подключиться.
Я пробовал другие порты в коде и через Telnet, включая 25, 80 и 8080. Telnet выдает порт 25, но мое приложение, похоже, читает первый цикл независимо от того, какой порт я ему скажу.
Вот мой код, который работает на клиентах:
int sendUsingTcp(string location) {
string result = string.Empty;
try {
using (FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read)) {
using (TcpClient client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) {
byte[] riteBuf = new byte[client.SendBufferSize];
byte[] readBuf = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream()) {
if ((ns.CanRead == true) && (ns.CanWrite == true)) {
int len;
string AOK = string.Empty;
do {
len = fs.Read(riteBuf, 0, riteBuf.Length);
ns.Write(riteBuf, 0, len);
int nsRsvp = ns.Read(readBuf, 0, readBuf.Length);
AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp);
} while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK")));
result = AOK;
return 1;
}
return 0;
}
}
}
} catch (Exception err) {
Logger.LogError("Send()", err);
MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0);
return -1;
}
}
Вот мой код, который работает на сервере:
SvrForm.Server = new TcpListener(IPAddress.Any, CpAppDatabase.ServerPortNumber);
void Worker_Engine(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = sender as BackgroundWorker;
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.CompanyName);
if (Directory.Exists(path) == false) Directory.CreateDirectory(path);
Thread.Sleep(0);
string eMsg = string.Empty;
try {
SvrForm.Server.Start();
do {
using (TcpClient client = SvrForm.Server.AcceptTcpClient()) { // waits until data is avaiable
if (worker.CancellationPending == true) return;
client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
string location = Path.Combine(path, string.Format("Acp{0:yyyyMMddHHmmssff}.bin", DateTime.Now));
byte[] buf = new byte[client.ReceiveBufferSize];
try {
using (NetworkStream ns = client.GetStream()) {
if ((ns.CanRead == true) && (ns.CanWrite == true)) {
try {
int len;
byte[] AOK = Encoding.ASCII.GetBytes("AOK");
using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write)) {
do {
len = ns.Read(buf, 0, client.ReceiveBufferSize);
fs.Write(buf, 0, len);
ns.Write(AOK, 0, AOK.Length);
} while ((0 < len) && (ns.DataAvailable == true));
}
byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server");
ns.Write(okBuf, 0, okBuf.Length);
} catch (Exception err) {
Global.LogError("ServerForm.cs - Worker_Engine(DoWorkEvent)", err);
byte[] errBuf = Encoding.ASCII.GetBytes(err.Message);
ns.Write(errBuf, 0, errBuf.Length);
}
}
}
}
worker.ReportProgress(1, location);
}
} while (worker.CancellationPending == false);
} catch (SocketException) {
// See MSDN: Windows Sockets V2 API Error Code Documentation for detailed description of error code
e.Cancel = true;
} catch (Exception err) {
eMsg = "Worker General Error:\r\n" + err.Message;
e.Cancel = true;
e.Result = err;
} finally {
SvrForm.Server.Stop();
}
}
Почему мое приложение не продолжать чтение от клиента TCP ? Не пренебрегал ли я установкой того, что говорит о том, что Socket остается открытым до тех пор, пока я не закончу? Код сервера никогда не видит исключения, потому что TCP-клиент никогда не останавливается, поэтому я знаю, что ошибки нет.
Наш сетевой администратор еще не получил степень Associates, поэтому, если это окажется проблемой на сервере, пожалуйста, подробно расскажите о том, как это разрешить, потому что мы можем не понимать, что вы говорите ,
Я прошу прощения за это так долго, но я хочу убедиться, что вы, люди, знаете, что я делаю, - и, возможно, даже прогляните какую-то информацию из моей техники!
Спасибо за помощь! ~ Джо
Не шутите? Думаю, теперь это имеет смысл. Я все думал о том, что нужно настроить на сервере. Это помогает * много *! Спасибо! – jp2code
как я могу это сделать? «предшествует отправленному контенту с длиной этого содержимого», у меня нет длины отправленного контента? –
Если вы не знаете длину, то, очевидно, вы не отправляете длину на проводе. – Amy