INDY自代的例子看了一下,以前用过TServerSocket做过这方面的东西!
TCommBlock = record // the Communication Block used in both parts (Server+Client)
Command: TCommand;
MyUserName, // the sender of the message
Msg, // the message itself
ReceiverName: string[100]; // name of receiver
end;
这是他里面的协议的定义,我这里需要的类似的MSN那种 ,先登录,然后是简单的信息通讯,客户大概100左右!我觉得INDY应该能承受的住!这个协议如何能定议的比较灵活,为以后扩展打下基础!希望大家讨论一下!或是有这方面的经验,交流一下!
TCommBlock = record // the Communication Block used in both parts (Server+Client)
Command: TCommand;
MyUserName, // the sender of the message
Msg, // the message itself
ReceiverName: string[100]; // name of receiver
end;
这是他里面的协议的定义,我这里需要的类似的MSN那种 ,先登录,然后是简单的信息通讯,客户大概100左右!我觉得INDY应该能承受的住!这个协议如何能定议的比较灵活,为以后扩展打下基础!希望大家讨论一下!或是有这方面的经验,交流一下!
解决方案 »
- 新手提问
- DELPHI7+SQL2000的日期型如何赋空日期值
- 怎么实现让DBGRID显示的行纪录随着鼠标的移动改变显示颜色?谢谢~
- r希望大家可以介绍几本了解Windows消息,WinShell,Delphi的VCL类库的经典之作??(dickman)没分了。
- 对Delphi7的编译器了解的朋友请指教。qtintf70.dll是干什么用的?
- 用delphi作和硬件连系多的程序的朋友请进!
- 关于table排序问题!
- 在D4中ShowModal一个自定义预览窗口可以在D5中却不行,为何?
- 菜鸟级中的菜鸟问题,急急急!!!!!!
- 谁可以提供Delphi 5的serial和auth key
- 请问如何将String类型转换成TByteDynArray类型?
- 自定义控件安装使用时如何加载多个单元.
最好好是udp-p2p,你用tcp想转发吗? 不好,特别是语音,视频聊天,
我自己写的一般是定义大包(包头+包身),接收读包头,确定内容什么再读,
这个是简单的思路
其实暂时没那么复杂,暂时只有文字的互相传递!但是要为以后扩展做好准备,所以各方面要考虑的比较多。
TO halfdream(哈欠):嗯,我想应该先看一下MSN的协议,必究他的是典型的TCP转发的模式!
TO constantine(飘遥的安吉儿) :因为用户连接数不太多,所以直接用INDY的TCP我觉得足够,如果要考虑大用户还有从完成端口方面考虑!
比如包头用byte类型,并定义成常量,代表不同的数据包。
数据包就按需求定义了,比如有登陆包、聊天信息包等。
接收时先接包头,分析包头后就可以接收不同的数据包了。以后扩展,增加新的数据包和数据头就可以了。如果是视频音频等数据,需要用数据流接收,同样使用这种包头和数据流分开的结构。
TCommBlock = record // the Communication Block used in both parts (Server+Client)
Command: TCommand;
MyUserName, // the sender of the message
Msg, // the message itself
ReceiverName: string[100]; // name of receiver
end;
这可能就是一个聊天包,包头可能需要定义一个BYTE的值,1可能为聊天包,接收时如何做呢,用MEMORYSTREAM接收,还是先接收包头,然后跟着接收包内容!谢谢
TCommBlock = record // the Communication Block used in both parts (Server+Client)
Command: TCommand;
end;TBlock = record // the Communication Block used in both parts (Server+Client)
MyUserName, // the sender of the message
Msg, // the message itself
ReceiverName: string[100]; // name of receiver
end;
end;
发送用WriteBuffer,分两次发;
接收用ReadBuffer(CommBlock,sizeof(TCommBlock));先接收包头,接着就知道包体是哪个,大小是多少了,还是用ReadBuffer接收
但会不会出现不同步的情况?接到包头,包内容发送太快而丢包或其他情况呢??!!!
procedure TServerFrmMain.Button1Click(Sender: TObject);
var
i: integer;
ActClient: PClient;
RecThread: TIdPeerThread;
NewCommBlock: TCommBlock;
begin
try
for i := 0 to Clients.LockList.Count - 1 do
begin
NewcommBlock.Command := cMessage;
NewcommBlock.MyUserName := 'system';
NewcommBlock.Msg := 'system test';
NewcommBlock.ReceiverName := '';
ActClient := Clients.LockList.Items[i];
RecThread := ActClient.Thread;
RecThread.Connection.WriteBuffer(NewCommBlock, SizeOf(NewCommBlock), True);
end;
finally
Clients.UnlockList;
end;
end;
我做了一个群发的测试,群发没问题,但当群发后,SERVER接收不到客户端的任何消息!!怀疑是TThreadList的问题,但是procedure TServerFrmMain.ServerExecute(AThread: TIdPeerThread);里发任何东西没有这样的问题,是线程安全,同步,还是什么问题??希望大家帮忙 !!
——————————————————————————
不会。tcp/ip协议是传输可靠的,不会丢数据
——————————————————————————————————
第二个问题,没看出什么不对来呀,这样试试
procedure TServerFrmMain.Button1Click(Sender: TObject);
var
i: integer;
ActClient: PClient;
RecThread: TIdPeerThread;
NewCommBlock: TCommBlock;
begin
try
for i := 0 to Clients.LockList.Count - 1 do
begin
NewcommBlock.Command := cMessage;
NewcommBlock.MyUserName := 'system';
NewcommBlock.Msg := 'system test';
NewcommBlock.ReceiverName := '';
ActClient := Clients.LockList.Items[i];
RecThread := ActClient.Thread;
finally//这里
Clients.UnlockList;
end;
RecThread.Connection.WriteBuffer(NewCommBlock, SizeOf(NewCommBlock), True);
end;
end;
另外是不是客户端那边有问题?
procedure TServerFrmMain.ServerConnect(AThread: TIdPeerThread);
var
NewClient: PClient;
NewCommBlock: TCommBlock;
begin
GetMem(NewClient, SizeOf(TClient));
NewClient.DNS := AThread.Connection.Socket.Binding.PeerIP;
NewClient.Connected := Now;
NewClient.LastAction := NewClient.Connected;
NewClient.Thread :=AThread;
AThread.Data:=TObject(NewClient);
// Clients.UnlockList;
try
Clients.LockList.Add(NewClient);//执行到这句,SERVER没有效果!
finally
Clients.UnlockList;
end;
end;
CLIENT显示连接,但是收、发消息都无效,看来还是TThreadList的问题,TThreadList是线程安全的应该没有同步等方面的安全问题,搞不清问题在哪里!!!
问题还是出现在TThreadList上面,
procedure TServerFrmMain.Button1Click(Sender: TObject);
var
i: integer;
ActClient: PClient;
RecThread: TIdPeerThread;
NewCommBlock: TCommBlock;
begin
try
for i := 0 to Clients.LockList.Count - 1 do//这句,每次循环一个对象,都会EnterCriticalSection 一次,这样就会导致程序不可以继续运行,
改为with Clients.LockList DO 这样就会保证只执行一次EnterCriticalSection !begin
NewcommBlock.Command := cMessage;
NewcommBlock.MyUserName := 'system';
NewcommBlock.Msg := 'system test';
NewcommBlock.ReceiverName := '';
ActClient := Clients.LockList.Items[i];//此处改为ActClient := Items[i];
RecThread := ActClient.Thread;
finally//这里
Clients.UnlockList;
end;
RecThread.Connection.WriteBuffer(NewCommBlock, SizeOf(NewCommBlock), True);
end;
end;
通过查看TThreadlist的源码,然后自定义一个TMYThreadList类,为跟踪使用!这个问题其实大家很容易犯的,如果不看源码或跟踪一下,不容易找到答案的,希望与大家分享一下!
我定义一个record
TMyMsg = record iType : integer; // 操作类型: 1 :登录 2:改变状态 3:发送信息 ...
UserName : String[255];
Pwd : String[255];
RecName : String[255];
sMsg : String[255];
iFile : integer;
sFileName : String[255];
iSize : int64;
sIP : String[255];
... //根据自己需要加
istat : smallint; // 用户状态: 0 :正常 1:隐身 2:忙碌 3:离开... 9 : 离线
SendTime : String[50]; //登录返回值 : -1:用户名或密码错误 0:登录成功 1:已经登录 9 :异常每次发送和接收都是这个record,那样你只要判断iType值就可以进行各种处理了,目前我做的基本聊天功能都实现了,就差像MSN或者QQ那样的在线、隐身、忙碌那样的图标了,哪位兄弟有给我发一个啊,感谢感谢 :) [email protected]