предисловие:
Я уже давно нахожусь в тупике, и мне не очень повезло найти то, что мне нужно.
У меня есть служба C # (.NET 3.5). Один поток действует как асинхронный прослушиватель для входящих соединений TCP. Когда данные поступают, я порождаю новый рабочий поток для обработки данных и отправляю подтверждение обратно.
Во втором потоке того же сервиса мы отправляем команды, до сегодняшнего дня он собирал информацию из базы данных, строил новый сокет, подключался, затем отправлял команду, и я использую Socket.Receive для вызова блокировки и дождитесь ответа (или пока не истечет время ожидания).
Все работало отлично, пока новому клиенту не нужно было отправлять нам данные так быстро (с интервалами в 5-10 секунд), что мы больше не можем открывать новый сокет, чтобы выполнить команду. Поэтому я начал изучать, когда нужно отправить команду, чтобы к потоку «слушателя» был подключен клиент. Если этот клиент подключен, используйте этот сокет вместо создания нового.
Проблема:
Я дошел до того, что могу отправить свою команду обратно в тот же сокет, который получает слушатель, но когда клиент отправляет данные обратно в качестве ответа, он дважды использует метод Socket.Receive для фактического запуска, думая, что он получил данные. Первый раз он попадает в мой класс слушателя, второй раз - в мой командный класс, где я действительно хочу, чтобы он был.
Вопрос:
Есть ли какая-либо опция или что-то, что мне нужно сделать перед вызовом моего метода Socket.Receive, чтобы убедиться, что данные попадают в правильное место?
В моем классе слушателя у меня есть список объектов "CSocketPacket"
public class CSocketPacket
{
public CSocketPacket(System.Net.Sockets.Socket socket)
{
thisSocket = socket;
this.IpAddress =
((System.Net.IPEndPoint)socket.RemoteEndPoint).Address.ToString();
}
public System.Net.Sockets.Socket thisSocket;
public byte[] dataBuffer = new byte[BUFFER_SIZE];
public string IpAddress; //Use this to search for the socket
}
Затем, когда я посылаю команду, я создаю новый объект сокета tcp:
client = new Socket(
AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(
IPAddress.Parse(Strings.Trim(ipAddress)), port);
IPEndPoint LocalIp = new IPEndPoint(IPAddress.Parse(
System.Configuration.ConfigurationManager.AppSettings["SourceIP"]), port);
затем я просматриваю список своих слушателей, чтобы узнать, подключен ли этот сокет:
if (listener.SocketExists(ipAddress))
{
// set the client socket in this class to the
// instance of the socket from the listener class
SocketIndex = listener.FindSocketInList(ipAddress);
if (SocketIndex != -1)
{
// might need to figure out how to avoid copying the socket
// to a new variable ???
client = listener.ConnectedSockets[SocketIndex].thisSocket;
SocketBeingReUsed = true;
}
}
else
{
// try to connect to the client
client.Connect(ep);
}
наконец я прошёл все этапы отправки и получения
if (client.Connected)
{
if (client.Poll(1000, SelectMode.SelectWrite))
{
int sentAmount = Send(ref client);
client.ReceiveTimeout = 90000; //90 seconds
returnData = ReceiveData(ref client, sentAmount);
}
}
все работает до точки в моем методе ReceiveData (ref client, sentAmount), где я вызываю метод Socket.Receive(data, total, Socket.ReceiveBufferSize, SocketFlags.None);
.
Я использовал инструмент под названием Hercules для проверки отправки / получения пакетов на двух машинах в моей домашней сети.
У кого-нибудь есть идеи, что я могу сделать, чтобы решить эту проблему? Я прошу прощения за такой длинный вопрос, но я хочу попытаться дать как можно больше информации, а не вставлять весь мой проект. Я за любые предложения.
Отказ от ответственности: я написал этот код около 3 лет назад, так что я стараюсь делать то, чего не должен быть, я уверен : P
Спасибо всем, кто это прочитал.
С уважением,
Chris