关于端口监听的问题(100分)

  • 主题发起人 主题发起人 hengheng
  • 开始时间 开始时间
H

hengheng

Unregistered / Unconfirmed
GUEST, unregistred user!
一服务器与多个(20-30)客户端通过internet 用udp 通讯
通讯
每个客户端定时(隔2分钟),与服务器通讯,从客户端上传简短数据(几十byte),服务器只接收次数据,不做应答。
同时每个客户端不定时响服务器通讯发送一定量的数据(1k -2k),服务器应答接收(返回成功标志)
请问 用多线程如何实现?最好有详细说明和源代码(注:本人是新手,请大家多帮忙!)

 
大家都说点吧,我很需要帮助
 
先用www.google.com去找中文资料,找到后仔细看看,如果碰到问题再来发帖子
 
听了无忌兄的话在网上找了不少资料,研究了几天,由于本人对这方面的资料不熟,有很多不太清楚的地方
总结一下:用两个线程完成,一个线程接收(把数据暂存于链表中),一个线程在链表中取数据处理,两个线程用互斥的方法同步。
问题1:这种接收线程不太会写(是用socket api还是有现成的类可以做到),请大哥给点指点,最好有源码。
问题2:可否用idudpserver控件实现(我知道他是非阻塞),如果用它实现,他接收时怎么与数据处理线程同步
问题3:由于只能使用udp,而udp一次不能传数过多(500byte下),所以接收要重组数据包,请问有什么好方法实现吗?

我很着急 希望得到帮助,如果您有更好的方法请告诉我吧,我得太少了,将来有了一定补上在线等待
e-mail:li_jiheng@yahoo.com.cn
 
问题一:你干脆就用TIdUDPServer,
问题二:数据处理线程同步你用队列来处理。用临界区来管理
问题三:自己把大的数据包分割,加上编号处理
 
非常感谢无忌
我先试一下!
 
to 无忌兄
我写了一个实验程序,有问题,请指正
数据处理线程如下:
procedure datathread.Execute;
var
num:integer;
begin
{ Place thread code here }
try
FreeOnTerminate:=True;
while not Terminated do
begin
entercriticalsection(cs);
num := data_list.length;
if num<>0 then
begin
form1.Memo1.Lines.Add(data_list.Items(0).td_ip+ ':' +
inttostr(data_list.Items(0).td_port)+ ':'+
data_list.Items(0).td_data);
data_list.Delete(0);
//我用的链表存储数据
end;
leavecriticalsection(cs);
sleep(1000);
{ 出错:project project_main.exe raised exception class EaccessViolation
with message'Access violation at address 00000000.Read of address 00000000'.
process stopped.Use Step or Run to contionuel
sleep(2000)运行时不出错,但程序退出时,也出同样的错,这个问题可能很菜,但我是新手,请一定帮忙!}

end;
except
showmessage('error');
end;
end;

idudpserver 接收代码:
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var
DataStringStream: TStringStream;
str:string;
re_data:tdata;
begin
DataStringStream := TStringStream.Create('');
try
DataStringStream.CopyFrom(AData, AData.Size);
str:= DataStringStream.DataString;
if leftstr(str,1)='0' //小数据
then memo2.Lines.Add(str)
else if leftstr(str,1)='1' //小数据
then memo3.Lines.Add(str)
else//需要处理的数据
begin
re_data.td_ip:= ABinding.PeerIP;
re_data.td_port:= ABinding.PeerPort;
re_data.td_data:=str;
data_list.Append(re_data);
end;

finally
DataStringStream.Free;
end;
end;
还有就是如客户端发送间隔太小如两个每个20毫秒法一次,有丢失,(应用中这种情况应很少发生,但不是不可能,请问有没有好方法)
 
对于UDP,丢数据是难一避免,不过减少接收处理数据的时间可以减少这个问题的发生,上
面的代码太长了,而且你处理VCL可示类没有用保护方法,出错再所难免
 
无忌老兄
我把对可视类的操作去掉了,还是同样出错 sleep(1000)
{ 出错:project project_main.exe raised exception class EaccessViolation
with message'Access violation at address 00000000.Read of address 00000000'.
process stopped.Use Step or Run to contionuel
sleep(1000)刚运行就出错
sleep(2000)运行时不出错,但程序退出时,也出同样的错,}
请一定帮忙,我都急死了

 
程序退出时错误提示:
project project_1.exe raised exception class EaccessViolation
with message'Access violation at address 004594A3 in module 'project1.exe'.Read of address 00000220'.process stopped.Use Step or Run to contionuel
那里的毛病,请帮我!
程序如下
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StrUtils,IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer,IdSocketHandle,
StdCtrls,Contnrs;

type
TForm1 = class(TForm)
IdUDPServer1: TIdUDPServer;
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
Memo3: TMemo;
procedure IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
datathread = class(TThread) { 声明线程类 }
private
protected
procedure ddd;
procedure Execute; override;{ 执行线程的方法 }
public
constructor Create(); virtual; { 线程构造器 }
end;
var
Form1: TForm1;
cs:trtlcriticalsection;
gcount:integer;
mcount:integer;
implementation

{$R *.dfm}
procedure datathread.ddd;
begin
form1.Memo1.Lines.Append(inttostr(gcount)+':'+inttostr(mcount));
end;
procedure datathread.Execute;

begin
{ Place thread code here }
try
FreeOnTerminate:=True;
while not Terminated do
begin
entercriticalsection(cs);
if gcount >0 then
dec(gcount);
leavecriticalsection(cs);
synchronize(ddd);
sleep(100);
end;
except
showmessage('threaderror');
end;
end;
constructor datathread.Create();
begin
inherited Create(False);
FreeOnTerminate := True;
end;
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var
DataStringStream: TStringStream;
str:string;
begin
DataStringStream := TStringStream.Create('');
try
DataStringStream.CopyFrom(AData, AData.Size);
str:= DataStringStream.DataString;
if leftstr(str,1)='0'
then sleep(2)//memo2.Lines.Add(str)
else if leftstr(str,1)='1'
then sleep(2)//memo3.Lines.Add(str)
else
begin
inc(gcount);
inc(mcount);
end;

finally
DataStringStream.Free;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
gcount:=0;
mcount:=0;
initializecriticalsection(cs);
idudpserver1.Active:=true;
datathread.Create();
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
deletecriticalsection(cs);
end;

end.
 
我知道有一本《delphi深度遍历——多线程解决》中有你想要的程序实例,你可以参考一下!
 
多人接受答案了。
 
你程序退出时,没有停线程,他还在使用cs,而此时你已经deletecriticalsection(cs);
。。。。。。。。。。。。。。。
 
后退
顶部