Ошибка сокета TCP в C# - 10060
У меня есть служба Windows, выступающая в качестве сервера. И я запускаю одну форму окна приложения localhost в качестве клиента. Обе программы используют TCP-соединение для отправки / получения данных. Сервер прослушивает порт 8030. Программа работает нормально.
Но когда я улучшил клиентскую программу для связи через определенный порт, скажем, 9030. При подключении к серверу генерируется следующее исключение.
Попытка подключения не удалась, потому что подключенная сторона не ответила должным образом через определенный промежуток времени, или не удалось установить соединение, так как подключенный хост не ответил 192.168.10.198:8030
Любое предложение будет высоко оценено.
Спасибо, Мадхусмита
Для справки
Код программы сервера
public partial class TestService : ServiceBase
{
Socket serverSocket = null;
public Timer timer1;
IPEndPoint ipEndPoint;
public TestService()
{
InitializeComponent();
timer1 = new Timer(10000);
timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Application", "Service started", EventLogEntryType.Information, 555);
try
{
ipEndPoint = new IPEndPoint(IPAddress.Any, 8030);
//Defines the kind of socket we want :TCP
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
//Bind the socket to the local end point(associate the socket to local end point)
serverSocket.Bind(ipEndPoint);
//listen for incoming connection attempt
// Start listening, only allow 10 connection to queue at the same time
serverSocket.Listen(10);
timer1.Start();
}
catch (SocketException ex)
{
EventLog.WriteEntry("Application", ex.ErrorCode + "-" +ex.Message, EventLogEntryType.Error, 555);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
}
}
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
// The program is suspended while waiting for an incoming connection.
// This is a synchronous TCP application
Socket handler = serverSocket.Accept();
byte[] fileDetails = new byte[1500];
//Recieve the file details
handler.Receive(fileDetails);
int fileNameLength = BitConverter.ToInt32(fileDetails, 0);
string fileName = Encoding.ASCII.GetString(fileDetails, 4, fileNameLength);
int fileLength = BitConverter.ToInt32(fileDetails, 4 + fileNameLength);
FileStream fs = new FileStream(@"C:\Demo\" + fileName, FileMode.Append, FileAccess.Write);
int byteRead = 0;
while (byteRead < fileLength)
{
byte[] data = new Byte[1500];
//Recieve teh data and write to the file
int r = handler.Receive(data);
fs.Write(data, 0, r);
byteRead += r;
}
fs.Close();
EventLog.WriteEntry("Application", "File saved successfully", EventLogEntryType.SuccessAudit, 555);
EndPoint endPoint = (EndPoint)ipEndPoint;
handler.Send(Encoding.ASCII.GetBytes("Done"));
handler.Close();
}
catch (SocketException ex)
{
EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
}
catch (IOException ex)
{
EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
}
}
protected override void OnStop()
{
timer1.Stop();
}
protected override void OnPause()
{
timer1.Stop();
}
protected override void OnContinue()
{
timer1.Start();
}
protected override void OnShutdown()
{
timer1.Stop();
}
}
Код клиентской программы
public partial class Form1 : Form
{
Socket socketClient;
IPEndPoint remoteEndPoint;
public Form1()
{
InitializeComponent();
}
private void buttonX1_Click(object sender, EventArgs e)
{
try
{
//Code to connect to server by by specifing the IP and port of the server on
//which the server application is hosted
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress,(int)1);
//IP address of the machine where the server program is hosted
IPAddress remoteIPAddress = IPAddress.Parse(txtXIPAddress.Text.Trim());
//Specify the specific port no thart the server listens to accept the data
int port = int.Parse(txtXPort.Text.Trim());
remoteEndPoint = new IPEndPoint(remoteIPAddress, port);
**//This two line causing the exception**
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9030);
socketClient.Bind(endPoint);
//Establish the connection to server
socketClient.Connect(remoteEndPoint);
MessageBox.Show("Connection established. Please select a file to send.");
}
catch (SocketException ex)
{
MessageBox.Show(ex.ErrorCode.ToString() + "-" + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnXBrowse_Click(object sender, EventArgs e)
{
if (socketClient != null)
{
openFileDialog1.ShowDialog();
}
else
{
MessageBox.Show("Please connect to the server first");
}
}
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
txtXFile.Text = openFileDialog1.FileName;
}
private void btnXTransfer_Click(object sender, EventArgs e)
{
//Check if the socket is connected to the remote host
//otherwise prompt user to get connected to the server first
if (socketClient != null && socketClient.Connected)
{
//If any file is selected then only proceed with transfer
if (!openFileDialog1.FileName.Equals(string.Empty))
{
FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
try
{
//Get the filename
string filename = Path.GetFileName(openFileDialog1.FileName);
//Covert the file name in form of byte
byte[] fileNameByte = Encoding.ASCII.GetBytes(filename);
//4- to store the filename length(as int - 4bytes)
//8- to stote the file content length(as long take 8 bytes)
int totalLength = 4 + fileNameByte.Length + 8;
//Clientdata[] reprents the data to sent to the server
//which represent the file details
byte[] clientData = new byte[totalLength];
byte[] fileNameLength = BitConverter.GetBytes(fileNameByte.Length);
byte[] fileContentLength = BitConverter.GetBytes(fs.Length);
//Copy all the data ClientData array
fileNameLength.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileContentLength.CopyTo(clientData, 4 + fileNameByte.Length);
//Send the data to server
socketClient.Send(clientData);
int byteRead = 0;
int bytesToRead = (int)fs.Length;
while (bytesToRead > 0)
{
byte[] data = new Byte[1500];
byteRead = bytesToRead > 1500 ? 1500 : bytesToRead;
int n = fs.Read(data, 0, byteRead);
//Send the data to server
socketClient.Send(data);
bytesToRead -= n;
}
//Code block to get the success message from server
byte[] successmessage = new byte[4];
int msg = socketClient.Receive(successmessage);
if (Encoding.ASCII.GetString(successmessage).Equals("Done"))
{
MessageBox.Show("transfered the file successfully");
txtXFile.Text = string.Empty;
openFileDialog1.FileName = string.Empty;
}
}
catch (SocketException ex)
{
MessageBox.Show(ex.ErrorCode + "-" + ex.Message);
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
fs.Close();
if (socketClient != null && socketClient.Connected)
{
socketClient.Shutdown(SocketShutdown.Both);
socketClient.Close(); ;
}
}
}
else
{
MessageBox.Show("Please select afile to transfer.");
}
}
else
{
MessageBox.Show("Please connect to the host.");
}
}
}
1 ответ
Примечание: вам не нужно привязывать локальный конец клиентского сокета - фреймворк и / или ОС будут связываться с эфемерным портом автоматически. Фактически, если вы привязываете сокет к 127.0.0.1, предполагая, что подключение не вызывает исключение о недоступных хостах, произойдет одно из двух (я не уверен, какой именно):
- Клиент попытается подключиться к серверу, но, поскольку локальный конец привязан к IP-адресу интерфейса обратной связи, он будет отправлять его по сети, а не по сети. -или же-
- Клиент правильно направит пакет через сетевую карту, и сервер получит его. Сервер отвечает "ОК, давайте настроим это соединение" клиенту... но, поскольку клиент сказал, что его адрес был 127.0.0.1, именно здесь сервер будет пытаться подключиться. Используя свой собственный петлевой интерфейс, потому что именно туда направляется 127.0.0.1.
В любом случае пакеты теряются в одном из интерфейсов обратной связи машины, и клиент никогда не увидит ответ.
Если вам необходимо подключиться к клиенту, выберите свой реальный IP-адрес или используйте IPAddress.Any
, вот так:
var endPoint = new IPEndPoint(IPAddress.Any, 9030);
Это будет привязано к данному порту, но все же позволит ОС выбирать IP-адрес. Но 127.0.0.1, вероятно, не будет работать.