关于写即时通讯的一些基本问题!
以前没有接触过网络通讯,现在准备写一个即时通讯的工具,要实现如下功能:
1.同时在线1000人左右聊天
2.音频、视频聊天
3.文件传输
4.简单的对战游戏
5.可以群聊,也可以点对点的聊天
现在的问题是用BCB戴的TSocketServer和TSocketClient能不能实现上述功能,性能如何。因为我搜索了以前的帖子好像用两个控件不如直接用Socket API那样好。我对Socket API几乎没有了解,请推荐一本Socket API编程的书。
问题点数:50、回复次数:29Top
1 楼ccrun(老妖)(www.ccrun.com)回复于 2005-11-02 16:01:52 得分 0
大工程啊老弟。Top
2 楼FengSC(小猪快跑)回复于 2005-11-02 16:47:22 得分 0
如果你对socket api都没有了解,那么这样的系统,够你研究个3~5年了Top
3 楼bcbnewbie()回复于 2005-11-02 17:59:58 得分 0
3~5年太夸张了吧,基本的TSocketServer、TSocketClient还是会用的,就是怕性能上不去。Top
4 楼zwq_2002(抗战时期)回复于 2005-11-02 18:57:40 得分 0
socket上面没什么复杂内容,主要是性能的优化,要涉及到服务器设计模型Top
5 楼niiv(一叶)回复于 2005-11-03 16:06:50 得分 0
只要带宽足够,TSocketServer、TSocketClient一点问题都没有。
不明白为什么经常有人说TSocketServer、TSocketClient性能不好,用了好多年,感觉效率很高,也很稳定。
很好奇,如果1000人都在大厅里公开发言,会是怎么样的一个情境。屏幕应该滚得很快吧?QQ好象一个聊天室最多也就允许180个用户吧?Top
6 楼pp616(坏蛋)回复于 2005-11-03 19:28:11 得分 0
《windows网络编程》人邮的 去看吧。 对你会非常有帮助。Top
7 楼godoli(snoogod)回复于 2005-11-04 15:38:46 得分 0
《Windows网络编程技术》比较好。 BCB中使用的是Winsock 1.1版本。TSocketServer、TSocketClient中的非阻塞主要是通过select、WSAAsyncSelect、重叠I/O机制方法。处理SOCKET不是太多的情况是能够胜任的。向楼主说的1000多个,就应该考虑使用完成端口模型,这是BCB中的控件无法完成的,必须要使用Winsock 2.2版本,这个版本中的对重叠I/O进行了自身的优化,不想BCB中使用的是WriteFile、ReadFile...
Top
8 楼pp616(坏蛋)回复于 2005-11-06 18:27:02 得分 0
楼上的你说的不对。
1.“TSocketServer、TSocketClient中的非阻塞主要是通过select、WSAAsyncSelect、重叠I/O机制方法。”
那2个控件非阻塞时用的就是WSAAsyncSelect模式 不存在select 和 重叠I/O 请你仔细阅读 scktcomp.pas
2.控件中WriteFile、ReadFile 的使用是在阻塞模式中使用的,在非阻塞中并未使用。
3.WriteFile、ReadFile 本身就可以用重叠I/O来做。
如果我说的不对请更正。
Top
9 楼DelphiGuy()回复于 2005-11-06 22:25:36 得分 0
就算你使用了线程池+重叠I/O+完成端口,
效率也不会比使用VCL Socket组件(自带的或者Indy)高超过5%。
不信你就试试。
我就用Indy处理过同时超过2000个TCP连接,
完全没有问题。
Top
10 楼songhtao(三十年孤独)回复于 2005-11-07 08:24:13 得分 0
Indy 很稳定,效率很好,而且跨平台。Top
11 楼wyb_45(小兵)回复于 2005-11-07 09:04:23 得分 0
socket api比较简单 也跨平台
就是要自己处理 多线程
WORD wVersionRequested;
WSADATA wsaData;
Sleep(100);
wVersionRequested=MAKEWORD(2,0);
int err=WSAStartup(wVersionRequested,&wsaData);
。。。
int Connect_Server(AnsiString host, u_short port)
{
int i, s;
long* p;
hostent* phe;
sockaddr_in sin;
DWORD Address;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
Address = inet_addr(host.c_str());
if (Address == INADDR_NONE) {
phe = gethostbyname(host.c_str());
if (phe) {
p = (long*)(*phe->h_addr_list);
sin.sin_addr.s_addr = *p;
}
}
else {
i = inet_addr(host.c_str());
if (i!=-1)
sin.sin_addr.s_addr = i;
}
s = socket(PF_INET,SOCK_STREAM,0);
if (s == INVALID_SOCKET)
return 0;
if (connect(s,(struct sockaddr FAR *)&sin,sizeof(sin))<0) // == SOCKET_ERROR) {
{
closesocket(s);
return(-1);
//int i = WSAGetLastError();
// return 0;
}
else
return s;
}
BOOL RecvStream(SOCKET s, TMemoryStream* Stream)
{
char buf[PACKAGESIZE];
//int namelen;
int pktlen;
int i = 1;
for (;;i++) {
Application->ProcessMessages();
if ((pktlen = recv(s,buf,sizeof(buf),0))<0) {
//接收数据失败
return false;
}
else if (pktlen == 0)
break;
else {
Stream->Seek(0,soFromEnd);
Stream->Write(buf,pktlen);
}
}
Stream->Seek(0,soFromBeginning);
closesocket(s);
return true;
}
if((pktlen =send(sockfd,buf,send_len,0))<=0)
{
。。。
break;
}
Top
12 楼bcbnewbie()回复于 2005-11-07 09:40:38 得分 0
谢谢大家回帖,我的想法就是服务器指转发更行IP的管理,然后客户端采用点对点直接联系。定义一些通讯命令字。还有一点疑问采用阻塞加线程的方式如果同时有几百个连接请求,服务器不是要同时开几百个线程对应,那不是对服务器的要求很高,,如果是非阻塞的方式,假设一个客户连接的请求处理很长时间,那么其他用户是不是可能会得不到服务?Top
13 楼constantine(飘遥的安吉儿)回复于 2005-11-07 12:37:27 得分 0
indy 很好我到不见的,还是有些不见人意,版本变化比较大,对于升级不好
如果你用TSocketServer和TSocketClient,那么是无法实现p2p的,p2p只能用udp
不过如果要简单用server转发很简单,不过这样会增加server的负担
另外你说的情况不会出现,既然是多线程,那么每个client的线程都是独立的,“那么其他用户是不是可能会得不到服务”这个不用担心
如果真要做到你提的要求,你可以考虑用indy的idudpserver控件来做Top
14 楼wangxiangsjz(王翔)回复于 2005-11-07 16:21:12 得分 0
http://www.loveunix.net/bbs/index.php?showtopic=22093Top
15 楼niiv(一叶)回复于 2005-11-08 11:34:33 得分 0
和 constantine(飘遥的安吉儿) 有类似感觉,Indy也不见得很好。
1000个客户端同时连接服务器时,TSocketServer可以3秒左右完成所有连接,如果每客户端通过服务器转发数据,每秒1K Bytes,服务器占用的资源几乎为0%。
注:测试PC,CPU=赛扬1G,内存=256M,出入口带宽最高达1MBytes/s。
UDP方面用Indy的好些Top
16 楼BCB2006(i like bcb)回复于 2005-11-08 13:47:36 得分 0
楼上的你是如何测试1000个并发连接的?如果是传送文件或语音视频呢?
这么说TSocketServer很强啊Top
17 楼niiv(一叶)回复于 2005-11-08 16:16:39 得分 0
测试结构如下:
服务器处于公网(电信级机房托管服务器),
服务器配置:CPU=赛扬1G,内存=256M,出入口带宽最高达1MBytes/s。
使用BCB的TSocketServer
客户端使用BCB的TSocketClient,生成1000个实例后,使用循环连接该服务器的同一端口(也就是相同IP的相同端口).
服务器端记录第1个连接到第1000个连接(OnAccept事件)的时间差。
最短时间3秒以下,一般在10秒左右。
个人用TSocketServer和TSocketClient有4年了,无论从效率和稳定性上都非常好,但也经常看到论坛上有人说丢包之类的问题,我没碰到过,估计是程序有问题。
To: BCB2006(i like bcb)
TSocketServer,无法区分你的数据是否为“文件或语音视频”,只视乎数据传送量。Top
18 楼bcbnewbie()回复于 2005-11-08 16:44:58 得分 0
谢谢大家回复!
想请教 niiv(一叶) 对于多人聊天的方案,就性能方面有什么看法。
比如说方案一由服务器转发用户的所有的数据包,服务器采用阻塞+多线程 或者非阻塞方式
第二种服务器转发登录用户的好友的IP,让登录用户和他的好友直接p2p的方式联系,在客户端用多线程+自己定义的消息格式。
那个更好一点,或则有更好的方案?Top
19 楼niiv(一叶)回复于 2005-11-09 15:57:04 得分 0
请留email/QQ/msn。Top
20 楼alloutoflove(andrew)回复于 2005-11-09 16:02:49 得分 0
偶是进来学习的.Top
21 楼bcbnewbie()回复于 2005-11-09 17:26:26 得分 0
qq:124271328]
bcbnewbie@21cn.com
谢谢!Top
22 楼constantine(飘遥的安吉儿)回复于 2005-11-09 17:35:52 得分 0
第二种好多了,现在的即时通基本上都是这样,但是不通的时候会让server转发Top
23 楼linuxghs()回复于 2005-11-09 20:27:09 得分 0
我也是用bcb开发的即时通讯软件,用的udp,现在效果很好
我用的也是第二种方法。除非是离线消息才要在server存储。Top
24 楼bcbnewbie()回复于 2005-11-09 20:30:13 得分 0
老兄,能留个QQ号交流一下吗?Top
25 楼Yans(跟贴是一种友谊)回复于 2005-11-14 14:14:17 得分 0
学习Top
26 楼dxkh(沧海一粟)回复于 2005-11-14 16:07:27 得分 0
确实是个大工程。。。Top
27 楼happyct(绿叶对大树的情怀)回复于 2005-11-14 16:29:55 得分 0
我做这个项目也做了3个月了。用的是delphi开发
用的TindyUdpServer,目的是P2P
目前已经具有的功能:
1. 文件收发:支持文件托放操作,收发过程中的信息交互(如取消、中止、错误),支持一对多发送
2. 信息收发:包括文字、手写信息、屏幕拷贝、表情图片(可自行添加),声音信息(即录音),这些信息可以混合编辑
3. 魔法表情:除系统提供的之外,用户可自由的自行添加
4. 屏幕震动
5. 输入状态提示功能,对方开始及结束输入都可以及时看到
6. 来信提示:托盘图标闪动、主窗体上方提示闪动、弹出提示窗口,任务栏闪动等
7. 头像设定及编辑:用户可自定义头像,系统提供了一个简单方便的编辑工具,可直接对头像进行设定编辑
8. 在线状态设定及个人文字说明
9. 历史消息查询功能(正在修改)
10. 临时群组(多方会谈):包括创建、添加、修改及删除。非组创建者只能添加用户,不能删除
11. 系统皮肤整体变色
12. 用户自定义链接。类似于收藏夹
插件接口:
消息收发接口
文件收发接口(其实就是一个插件)
上述功能已经完成,同时对50个在线用户的群聊没什么问题
同时对30个用户收发文件没什么问题
视频语音还没做Top
28 楼happyct(绿叶对大树的情怀)回复于 2005-11-14 16:34:20 得分 0
总结:
1、对于某某控件好,某某控件不好这样的评论,一般来说,都是不客观的。那是开发者自己水平问题(当然我的水平也不行)
2、要P2P,请用UDP,TCP没办法实现的,除非限于局域网或都是公网
3、请做好详尽的系统分析,工程约大,这项工作越重要。这个项目的的系统分析时间是1个月,除系统分析文档外,其他文档还没写
4、自我感觉速度还比较快,中间遇到过2次问题,都是安吉儿帮忙解决的,在此谢过Top
29 楼happyct(绿叶对大树的情怀)回复于 2005-11-14 16:37:23 得分 0
其中还做了几个不大不小的控件。有点模仿QQ和MSN的感觉。自我感觉不错。如果有需要的,可以向我索取,可惜不能贴图。Top




