Вопрос теоретический, можно ли использовать один буффер в нескольких send выполняющихся паралельно?
По логике, для функции send буффер константа и внутри стэк будет буффер только читать, и ничего вроде криминального нет если несколько паралельно-выполняющихся send будут отправлять один и тот же буфер. На практике, c# никаких проблем не испытывает в моем тестовом приложении. Но я не встречал примера или авторитетного источника что так делать можно или нельзя. Возможны ли здесь какие нить грабли?!
using System;
using System.Net;
using System.Net.Sockets;
namespace ReuseSocketBuffer
{
class Program
{
static byte[] reciveBuffer = new byte[1024];
static byte[] senderBuffer = new byte[1024];
static void Main(string[] args)
{
var sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 0));
listener.Listen(1);
var ar1 = listener.BeginAccept(null, null);
sender.Connect(new IPEndPoint(IPAddress.Loopback, (listener.LocalEndPoint as IPEndPoint).Port));
var receiver = listener.EndAccept(ar1);
receiver.BeginReceive(reciveBuffer, 0, reciveBuffer.Length, SocketFlags.None, ReceiveCallback, receiver);
var ee = new SocketAsyncEventArgs[1024];
senderBuffer[0] = 1;
senderBuffer[1023] = 2;
for (; ; )
{
for (int i = 0; i < ee.Length; i++)
{
ee[i] = new SocketAsyncEventArgs();
ee[i].SetBuffer(senderBuffer, 0, senderBuffer.Length);
}
for (int i = 0; i < ee.Length; i++)
sender.SendAsync(ee[i]);
}
}
static int count = 0;
static void ReceiveCallback(IAsyncResult ar)
{
var receiver = ar.AsyncState as Socket;
int received = receiver.EndReceive(ar);
if (received == 1024)
{
Console.Write("\r{0}", count++);
if (reciveBuffer[0] != 1 || reciveBuffer[1023] != 2)
throw new Exception();
receiver.BeginReceive(reciveBuffer, 0, reciveBuffer.Length, SocketFlags.None, ReceiveCallback, receiver);
}
}
}
}
Re: несколько send и один буффер
От:
Аноним
Дата:
13.01.11 06:43
Оценка:
Во первых, твой код никак не параллельно посылает, а вполне себе последовательно. Ну, допустим, ты будешь из разных потоков слать. В принципе, все будет ок — никаких исключений не будет, один и тот же буфер можно в разные операции ВВ засунуть, главное, чтобы его не удалили до завершения всех операций. Но СМЫСЛ всего этого???
Здравствуйте, Аноним, Вы писали:
А>Во первых, твой код никак не параллельно посылает, а вполне себе последовательно. Ну, допустим, ты будешь из разных потоков слать.
Я использую SendAsync, вероятность того что запаралелится очень высока. Хотя в чем то ты прав, я так только .net проверяю, а сам (в моем случае виндовый) стек внутри будет в рамках одного сокета синхронизироваться (вероятно), так что я попробовал отдавать один буфер в разные сокеты, проблем тоже не возникает.
А>В принципе, все будет ок — никаких исключений не будет, один и тот же буфер можно в разные операции ВВ засунуть, главное, чтобы его не удалили до завершения всех операций. Но СМЫСЛ всего этого???
В моем случае, для udp очень удобно (tcp я с горяча проверил)
Re[3]: несколько send и один буффер
От:
Аноним
Дата:
14.01.11 06:40
Оценка:
А>>Во первых, твой код никак не параллельно посылает, а вполне себе последовательно. Ну, допустим, ты будешь из разных потоков слать. vf>Я использую SendAsync, вероятность того что запаралелится очень высока.
Примерно 0.0
В твоем случае единственное, что может произойти этакого асинхронного — это приход нотификаций о завершении операций ВВ не в том порядке, в каком эти операции были иницированый.
Другими словами: данные уйдут в сеть именно в том порядке, в каком ты вызвал свои SendAsync. В этом смысле, нет никакой разницы вызывать в цикле SendAsync или блокирующий Send.
Re[3]: несколько send и один буффер
От:
Аноним
Дата:
14.01.11 06:50
Оценка:
А>>Но СМЫСЛ всего этого??? MC>Например, в буфере смикшированный звук от нескольких участников конференции, который надо отослать им всем.
Я хотел узнать СМЫСЛ приведенного кода. Очевидно, это просто какая то мусорилка ( для стресс тестов? ). Но какая то очень уж изощреная ))
А>В твоем случае единственное, что может произойти этакого асинхронного — это приход нотификаций о завершении операций ВВ не в том порядке, в каком эти операции были иницированый. А>Другими словами: данные уйдут в сеть именно в том порядке, в каком ты вызвал свои SendAsync.
Согласен, и сомнений это не вызывает, причем здесь это?! Я хотел проверить как tcp/ip стек относиться к тому что используется один и тот же буфер для нескольких одновременно выполняющихся Send, к примеру SocketAsyncEventArgs нельзя использовать подобным образом. В моем примере SendAsync может завершиться до того как данные SocketAsyncEventArgs будут обработаны, и будет вызван еще один SendAsync таким образом возникнет та ситуация которую я проверял — один и тот же буфер в стеке.
А>В этом смысле, нет никакой разницы вызывать в цикле SendAsync или блокирующий Send.
Заменив на Send ничего подобного я получить не смогу.
А>>>Но СМЫСЛ всего этого??? MC>>Например, в буфере смикшированный звук от нескольких участников конференции, который надо отослать им всем. А>Я хотел узнать СМЫСЛ приведенного кода. Очевидно, это просто какая то мусорилка ( для стресс тестов? ). Но какая то очень уж изощреная ))
Из первого поста>На практике, c# никаких проблем не испытывает в моем тестовом приложении.
Я имел ввиду что это приложения создано для проверки того о чем я спрашивал.
Здравствуйте, vf, Вы писали:
vf>Согласен, и сомнений это не вызывает, причем здесь это?! Я хотел проверить как tcp/ip стек относиться к тому что используется один и тот же буфер для нескольких одновременно выполняющихся Send,
В общем случае плохо относится — данные перемешаются.
Здравствуйте, netch80, Вы писали:
vf>>Согласен, и сомнений это не вызывает, причем здесь это?! Я хотел проверить как tcp/ip стек относиться к тому что используется один и тот же буфер для нескольких одновременно выполняющихся Send,
N>В общем случае плохо относится — данные перемешаются.
Как перемешаются, можно пример? Что подразумевается под общим случаем, под .нет, виндой проблем не видно, в других осях с чем-то сталкивался?
Здравствуйте, vf, Вы писали:
vf>>>Согласен, и сомнений это не вызывает, причем здесь это?! Я хотел проверить как tcp/ip стек относиться к тому что используется один и тот же буфер для нескольких одновременно выполняющихся Send, N>>В общем случае плохо относится — данные перемешаются. vf>Как перемешаются, можно пример?
Вместо одних данных будут прочтены другие, записанные для другого send().
Реальное чтение этих данных из буфера в оптимально написанном коде происходит не в момент входа в send(), а когда потребуется следующая порция для передачи уже в сокетные буфера.
vf> Что подразумевается под общим случаем, под .нет, виндой проблем не видно, в других осях с чем-то сталкивался?
Видимо, в дотнете копируется содержимое пользовательского буфера. Иначе я это объяснить не могу.
Практически везде в остальных местах этот фокус не пройдёт.
vf>Вопрос теоретический, можно ли использовать один буффер в нескольких send выполняющихся паралельно? vf>По логике, для функции send буффер константа и внутри стэк будет буффер только читать, и ничего вроде криминального нет если несколько паралельно-выполняющихся send будут отправлять один и тот же буфер.
Ну если в то время пока они будут отправлять буфер никто данные в нем не будет модифицировать — все будет хорошо.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
vf>>Вопрос теоретический, можно ли использовать один буффер в нескольких send выполняющихся паралельно? vf>>По логике, для функции send буффер константа и внутри стэк будет буффер только читать, и ничего вроде криминального нет если несколько паралельно-выполняющихся send будут отправлять один и тот же буфер. O>Ну если в то время пока они будут отправлять буфер никто данные в нем не будет модифицировать — все будет хорошо.
Хорошо-то хорошо, да вот такой вопрос. Какой там тип в/в при работе с сокетом в ядре используется : прямой или буферизованый ? Если буферизованный, то точно ничего интересного не будет, так как под каждый send будет делаться копия буфера в АП ядра. А вот если прямой — гм... Ядро при этом фиксирует буфер в физической памяти. А если он уже зафиксирован ? Что будет — возьмут зафиксированный уже буфер или будут ждать, пока его расфиксируют ?
vf>>>Вопрос теоретический, можно ли использовать один буффер в нескольких send выполняющихся паралельно? vf>>>По логике, для функции send буффер константа и внутри стэк будет буффер только читать, и ничего вроде криминального нет если несколько паралельно-выполняющихся send будут отправлять один и тот же буфер. O>>Ну если в то время пока они будут отправлять буфер никто данные в нем не будет модифицировать — все будет хорошо. PD>Хорошо-то хорошо, да вот такой вопрос. Какой там тип в/в при работе с сокетом в ядре используется : прямой или буферизованый ? Если буферизованный, то точно ничего интересного не будет, так как под каждый send будет делаться копия буфера в АП ядра. А вот если прямой — гм... Ядро при этом фиксирует буфер в физической памяти. А если он уже зафиксирован ? Что будет — возьмут зафиксированный уже буфер или будут ждать, пока его расфиксируют ?
MmProbeAndLockPages can be called multiple times for the same page. Each successful call to MmProbeAndLockPages for an MDL must be matched by a call to MmUnlockPages for the same MDL.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, netch80, Вы писали:
N>Вместо одних данных будут прочтены другие, записанные для другого send(). N>Реальное чтение этих данных из буфера в оптимально написанном коде происходит не в момент входа в send(), а когда потребуется следующая порция для передачи уже в сокетные буфера.
Нет, данные в буффере я не планирую менять пока все send'ы не завершаться. Тем более планируется SendAsync...
vf>> Что подразумевается под общим случаем, под .нет, виндой проблем не видно, в других осях с чем-то сталкивался? N>Видимо, в дотнете копируется содержимое пользовательского буфера. Иначе я это объяснить не могу. N>Практически везде в остальных местах этот фокус не пройдёт.