SocketException (10057) при попытке отправить данные
23.09.2013, 23:43. Показов 1716. Ответов 0
опишу методы в порядоке их вызова
класс Listener - обертка над Socket, выполняющего функцию сервера
C# | 1
2
3
4
5
6
7
| public Listener()
{
_Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Listener.Bind(new IPEndPoint(Extensions.ParseLocal(), Extensions.Port)); // два метода возвращают: первый - IP4 локальной машины, второй общий для всех соединений номер порта, в данном случае 22222
_Listener.Listen(_MaxConnections);
ListeningStarted.SafeRaise(this); // это, и все, что далее с методом-дополнением SafeRaise, всего-лишь события
} |
|
далее создается клиент и лезет подключаться к серверу
C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public Broadcaster()
{
_Broadcaster = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void Connect(IPAddress address)
{
_Broadcaster.BeginConnect(address, Extensions.Port, ConnectCallback, _Broadcaster);
}
void ConnectCallback(IAsyncResult result)
{
try
{
_Broadcaster.EndConnect(result);
Connected.SafeRaise(this);
}
catch (Exception e)
{
ThrowedException.SafeRaise(e);
}
} |
|
Тем временем, сервер принимает входящие подключения
C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| public void Listen()
{
if (_Cancelling)
return;
_Listener.BeginAccept(ListenCallback, _Listener);
}
void ListenCallback(IAsyncResult result)
{
try
{
var income = _Listener.EndAccept(result);
if (!_Cancelling && income != null)
{
_ConnectedClients.Add(income);
NewConnection.SafeRaise(income);
Recieve(income); // это метод, ловящий входящие данные, но до него пока не доходит
}
Listen();
}
catch (Exception e)
{
ThrowedException.SafeRaise(e);
}
} |
|
До сих пор пока все нормально. Далее, по событию Listener.NewConnection в основном коде приложения клиенту пересылаются рандомные данные:
C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| // код Main
server.NewConnection += (s, e) =>
{
Log("Server", "NewConnection event");
server.Send(_Buffer); // буфер - массив из сотни, сгенерированных Random.NextBytes методом
};
// код у сервера
public void Send(byte[] buffer)
{
if (_Cancelling)
return;
foreach (var client in _ConnectedClients)
if (_Cancelling)
break;
else
SendTo(client.RemoteEndPoint, buffer);
}
public void SendTo(EndPoint target, byte[] buffer)
{
var socket = _ConnectedClients.FirstOrDefault(s => s.RemoteEndPoint == target); // сюда были попытки влепить и LocalEndPoint, результат аналогичный
if (!_Cancelling && socket != null)
{
var data = new TransferObject(socket) { Data = buffer };
var connected = socket.Connected; // этот флаг возвращает true, т.е. подключение все еще держится
_Listener.BeginSendTo(data.Data, 0, data.Data.Length, SocketFlags.None, target, SendToCallback, data);
}
}
void SendToCallback(IAsyncResult result)
{
// первым делом, входя в этот коллбэк, инициируется исключение SocketException с кодом 10057, что означает отсутствие подключения между сокетами, если верить документации
try
{
var data = result.AsyncState as TransferObject;
var sent = _Listener.EndSendTo(result);
if (!_Cancelling && sent > 0)
DataSent.SafeRaise(data);
}
catch (Exception e)
{
ThrowedException.SafeRaise(e);
}
} |
|
Кто знает, где может быть ошибка?
Добавлено через 3 часа 3 минуты
Где-то здесь меня офиолетило найти причину выброса исключения
Кликните здесь для просмотра всего текста
омайнгот, все было чуть проще, чем казалось изначально. хотя, признаться, такую логику я никогда не пойму
проблема была в том, что в коде серверного класса я пытался воспользоваться методом Socket.BeginSendTo у экземпляра, который представлял собой сокет-слушатель этого самого сервера, направляя даные по нужному адресу, указанному в параметрах метода. это казалось мне логичным: серверу нужно отправлять -> именно серверный сокет и отправляет по адресу клиентского сокета. поэтому ошибку искать там мне и не пришло в голову
на самом деле, нужно сделать из:
C# | 1
2
3
4
5
6
7
8
9
| // код метода <сервер>.SendTo(EndPoint, byte[])
var socket = _ConnectedClients.FirstOrDefault(s => s.RemoteEndPoint == target);
if (!_Cancelling && socket != null)
{
var data = new TransferObject(socket) { Data = buffer };
var connected = socket.Connected;
_Listener.BeginSendTo(data.Data, 0, data.Data.Length, SocketFlags.None, target, SendToCallback, data);
} |
|
это
C# | 1
2
3
4
5
6
7
8
| // код метода <сервер>.SendTo(EndPoint, byte[])
var socket = _ConnectedClients.FirstOrDefault(s => s.RemoteEndPoint == target);
if (!_Cancelling && socket != null)
{
var data = new TransferObject(socket) { Data = buffer };
[B]socket[/B].BeginSendTo(data.Data, 0, data.Data.Length, SocketFlags.None, target, SendToCallback, data);
} |
|
ну и, естественно, в коде коллбэка произвести замену
C# | 1
2
| var data = result.AsyncState as TransferObject;
var sent = [B]data.Listener[/B].EndSendTo(result); // это есть ссылка на экземпляр Socket |
|
0
|