Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.08.2012, 16:56   #1
NewHorek
 
Регистрация: 18.04.2010
Сообщений: 5
По умолчанию Отправка UDP в потоке (winsock)

Добрый день. Кто подсказать может. Имеется код по отправке пакетов UDP. Без потока все работает нормально. Как только этот же код начинает работать в отдельном потоке, так пакеты больше 150 байт не уходят. Кто знает, в чем может быть проблемма.
Отрывок кода:

function UDP(p : pointer) : DWORD; stdcall;
var
SocketHwnd : TSocket;
SocketAddr : TSockAddr;
sUDPPacket : string;
iSleepTime : integer;
begin
SocketHwnd := Socket(AF_INET,SOCK_DGRAM,IPPROTO_U DP);
SocketAddr.sin_family := AF_INET;
SocketAddr.sin_addr.S_addr := '192.168.1.100';
SocketAddr.sin_port := htons(5000);

.
.
// sUDPPacket < 150 bytes - отправляется
// > нет
.
.

while bGo do
begin
SendTo(SocketHwnd,sUDPPacket,Length (sUDPPacket),0,SocketAddr,SizeOf(So cketAddr));
sleep(iSleepTime);
end;
end;


// основной поток

Windows.CreateThread(nil,0,@UDP,@UD PMessage,0,UDPID);
SetThreadPriority(UDPID,THREAD_PRIO RITY_NORMAL);

Кто знает, помогите...
NewHorek вне форума Ответить с цитированием
Старый 08.08.2012, 17:42   #2
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...вызывайте внешний метод отправки из потока через Synchronize().
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 08.08.2012, 18:53   #3
NewHorek
 
Регистрация: 18.04.2010
Сообщений: 5
По умолчанию

Попробовал, не помогло.
Оставил sendto в отдельной функции. Если перед первым посылом ставлю задержку, пакеты начинают уходить. Кто в курсе?

Последний раз редактировалось NewHorek; 08.08.2012 в 19:43.
NewHorek вне форума Ответить с цитированием
Старый 08.08.2012, 19:44   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...покажите как пробовали?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 08.08.2012, 19:47   #5
NewHorek
 
Регистрация: 18.04.2010
Сообщений: 5
По умолчанию

Уже перетер все. Через потомок от TThread (обычный поток в делфи)
Сейчас соорудил фун-ю
procedure M(SocketHwnd : integer; sUDPPacket : string; SocketAddr : TSockAddr);
var
i : integer;
begin
i := SendTo(SocketHwnd,sUDPPacket,Length (sUDPPacket),0,SocketAddr,SizeOf(So cketAddr));
MessageBox(0,PChar(IntToStr(i)),'', 0);
//sleep(10);
end;

Если есть sleep - пакеты уходят. Но это ведь не правильно!
Может как узнать свободность сокета?


Вопрос решил заменой sUDPPacket на динамический массив. Все заработало. Проблемму с предыдущим типом данных так и не понял....

Последний раз редактировалось NewHorek; 08.08.2012 в 20:21.
NewHorek вне форума Ответить с цитированием
Старый 08.08.2012, 21:45   #6
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...пакет не может быть неограниченной длины, да и для UDP пакеты лучше делать фиксированными и поменьше.

Насчет того, как синхронизировали, вы не показали, да и уже неактуально . Удачи.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 09.08.2012, 10:37   #7
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Сейчас попробуем помочь из твоего примера

Последний раз редактировалось Aliens_wolfs; 09.08.2012 в 10:47.
Aliens_wolfs вне форума Ответить с цитированием
Старый 09.08.2012, 10:37   #8
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Вот накидал простенький поток из твоего примера должен работать
Код:
var
  Form1: TForm1;
  FhEvent: THandle;
  sUDPPacket: string;
  UDPID: dword;

implementation

{$R *.dfm}

function UDP(p : pointer) : DWORD; stdcall;
var
SocketHwnd : TSocket;
SocketAddr : TSockAddr;
Size : integer;
begin
//Заполняем структуру
SocketHwnd := Socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
SocketAddr.sin_family := AF_INET;
SocketAddr.sin_addr.S_addr := inet_addr(PCHAR('192.168.1.100'));
SocketAddr.sin_port := htons(5000);

// Создаем Объект события - это что-то вpоде пеpеключателя: 
// у него есть только два состояния: вкл и выкл.
FhEvent := CreateEvent(nil, True, False, nil);

//крутим поток
while true do
begin
//ждем когда включать Объект события
WaitForSingleObject(FhEvent, INFINITE);
ResetEvent(FhEvent);
//отправляем данные
Size:= SendTo(SocketHwnd, sUDPPacket, Length(sUDPPacket), 0 , SocketAddr, SizeOf(SocketAddr));
if (Size = SOCKET_ERROR)then
break;
end;
UDPID:=0;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//Запускаем поток если значение его ID 0
if UDPID = 0 then
begin
CreateThread(nil,0,@UDP,nil,0,UDPID);
SetThreadPriority(UDPID,THREAD_PRIORITY_NORMAL);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 //Заполняем данные для отправки
 sUDPPacket:='fff';
 // включаем объект события чтобы данные отправились
 SetEvent(FhEvent);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
UDPID:=0;
end;

// следим за потоком и делаем кнопку его запуска недоступной если он уже запущен
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if UDPID = 0 then
Button1.Enabled:=true
else
Button1.Enabled:=false;
//Контроль кнопки отправления данных если поток работает то кнопка доступна
Button2.Enabled:= not Button1.Enabled;
end;
Для отправки больших данных нужно их отправлять частями и следить все ли отпавились, могу и с этим помочь
Еще можно сделать из класса TThread создать его тело и через него можно реализовать и передачу и прием данных

Последний раз редактировалось Aliens_wolfs; 09.08.2012 в 11:23.
Aliens_wolfs вне форума Ответить с цитированием
Старый 12.08.2012, 19:02   #9
NewHorek
 
Регистрация: 18.04.2010
Сообщений: 5
По умолчанию

Спасибо за пример. Учту. Правда вопрос решил применением динамических массивов. Причем:
massiv: array of byte;
SetLength(masssiv, len);

1. SendTo(handle, masssiv[0],... -работает,

Пакеты приходят (использовал commview) , причем, длина не имеет значения (ну логично < 65535 bytes). CommView показывает один пакет = MTU, остальные как defragment ( в сумме = len ).

Не понял проблемму с типом string? Почему поток отказывается работать.
Вот этого я не вкурил

Еще 1 фишка - данные при типе string (delphi 7, без unicode) в пакете не соответстуют исходным. При динамическом массиве все ОК...
Ладно бы я понял там смещение на пару байт в string с учетом организации строк паскаля. Но ведь нет. Бред какой-то. приходит.

Предположение: Поток, организованный CreateThread и BeginThread - отличаются в работе со строками (изменения в диспетчере пямяти не в счет)

Причем поток работает сам по себе, основной поток его только запускает, никаких синхронизаций данных не требуется, он сам в себе...

Последний раз редактировалось NewHorek; 12.08.2012 в 19:22.
NewHorek вне форума Ответить с цитированием
Старый 12.08.2012, 19:50   #10
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

Цитата:
Не понял проблемму с типом string? Почему поток отказывается работать.
Вот этого я не вкурил
еще раз про длины . Cколько тип string вмещает? Если бы вы определили как string[1000], 5000, 6000, ..., скажем, еще куда не шло.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
WinSock сервер в потоке vgbox Работа с сетью в Delphi 1 03.03.2012 06:42
winsock udp сервер в потоке, не работает при создании формы или обращению к VCL компоненту marikcool Работа с сетью в Delphi 1 01.10.2010 00:57
Winsock: UDP сервер под Win студент_88 Win Api 0 05.09.2010 22:01
WinSock, UDP, широковещание; delphi (pascal) svchaos Работа с сетью в Delphi 5 02.06.2009 14:44
WinSock, UDP, широковещание: Delphi (Pascal) svchaos Помощь студентам 8 01.06.2009 20:41