局域网C/S,服务器程序,主干千M,百M到桌面,为什么服务器程序只利用了5、6十M,其它网络程序如FTP什么的就上不去了??当50M以下时一点问题没有。服务器程序是对每个连接建立一个UDP SOCKET专门用于和该终端通信,也就是说开了200个左右SOCKET,带宽占用60M就不行了。通过任务管理器查看系统CPU利用20%,内存20%,用ONLINEEYE查看流量就在60M。请高手指点。问题如能解决,立即另开贴送1000分,顶也有分
解决方案 »
- 如何改变对话框大小(当调整窗口大小时)
- webbrowser在线程中使用的问题
- 新手紧急求助:点击树控件某一节点后,在列表控件里显示一些参数?
- 如何不调出扫描仪自带的界面直接扫描
- 【网龙之家 网址改变 以前和我连接过的朋友请重发一次 谢谢】 改为龙活小居 网址http://vip1.kudns.com/blsoftbl 二级域名http://bl
- 自定义消息的问题
- 计时器问题
- 大虾们:请你们帮我推荐几本关于学习com的书籍!
- 你精通Visual C++吗?
- 问个简单的问题,线程中发送消息,当前类不能接受,而主窗口能够接受,为什么呢???
- 关于SHGetFileInfo的破问题。。。
- QueryInterface中强制转换的问题
是用了多线程,两种模型,一种是对每个终端都建立一个线程,这时带宽能够达到150M都还正常,再高就不行了。另一种是对每个终端建立一个线程,在线程中建立SOCKET,SOCKET建立好后加入链表线程就结束,另有专门线程控制链表内的所有SOCKET的通信,有收有发。我已经设置UDP SOCKET非阻塞了。这种模型就是到5、60M带宽时,其他网络程序就连不上服务器了?怀疑是资源问题,又不能确定在哪里?或者模型有问题?
我说的就是bps,单位是统一的,因此我一直莫名其妙啊
系统CPU利用20%,内存20%。并不高啊。
是不是由于你用专门线程控制链表内的所有SOCKET的通信,使它是轮巡、或则排队的原因?
按道理即使这样也不该有带宽限制,纳闷中……
难道是收、发各占一半带宽??
2.建议每个UDP的CLIENT 都 CONNECT(虽然不用connet()但connect()后可假定
有一条虚拟连接);
3.用setsockopt()设置每个socket的缓冲区大小,而且用非阻塞模型;
4."另有专门线程控制链表内的所有SOCKET的通信" 不知道你的这句话的意思,你是开一个线程
处理如此过的I/O?(可以考虑分64个为一组,开一个线程)你的程序问题就应该在这里要优化!
1.首先如果用户数量超过了200 建立多线程是不现实的,建议用 链表后者是数组;
是的,因此我们放弃了方案1,而改用方案2,用链表。
2.建议每个UDP的CLIENT 都 CONNECT(虽然不用connet()但connect()后可假定有一条虚拟连接);
不知道有哪些优点,我们考虑试试。
3.用setsockopt()设置每个socket的缓冲区大小,而且用非阻塞模型;
我们是这样做的,
4."另有专门线程控制链表内的所有SOCKET的通信" 不知道你的这句话的意思,你是开一个线程
处理如此过的I/O?(可以考虑分64个为一组,开一个线程)你的程序问题就应该在这里要优化!
就是说整个程序用一个专门的线程来轮循控制各个SOCKET的收发,。也考虑过50个一组,每组用一个线程,一个链表,但还是到50M,200个SOCKET就阻塞了,我也觉得应该在这里优化,但摸不着头脑啊!
在服务器上做如下操作:
//如果在发送数据的时,希望不经历由系统缓冲区到socket缓冲区的拷贝而影响
//程序的性能:
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));
// 发送数据时候一般是系统缓冲区满以后才发送,现在设置为只要系统
//缓冲区有数据就立刻发送:
SetSockOpt(s,IPPROTO_TCP,TCP_NODELAY,(const char*)&bNodelayt,sizeof(BOOL));
4.如果你程序代码没什么问题,那我要考虑你系统,网卡(所有硬件设备)可能是它们
引起的瓶颈。
你的每个client 发送的数据包有多大? UDP 每次发送数据包的最大限制为64k,按照
这个极限考虑最少也应该有800个client 连接,所以我敢肯定,是你服务器的问题,
也就是服务器处理数据不及时,所以你线程处理是怎么处理I/O(循环接受,肯定错误)程序的瓶颈!!
我每次发送的数据不到1500字节,因考虑到MTU的限制,大约1400字节。对setsockopt,我是这样用的:
int nSnd=32768;
setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nSnd,sizeof(nSnd));
setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nSnd,sizeof(nSnd));
SetSockOpt(s,IPPROTO_TCP,TCP_NODELAY,(const char*)&bNodelayt,sizeof(BOOL));
而且硬件设备肯定不是造成这种现象的原因
经你的提醒,我现在怀疑是否是因为我的非阻塞模型用的不对。希望夜风微凉兄继续点播,谢谢!
----------
夜风微凉兄高见。我确实是循环接收的,因为我不确定终端什么时候给服务器发数据啊。流程如下:
for(;;)
{
p=first;
while(p=p->next)
{
p->sock.recvfrom(...);
bool bsend= ......//根据接收的命令数据判断是否需要发送
if(bsend)
{
p->sock.sendto(...);
}
}
}
1.
/*int nSnd=32768;//(32K)
setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nSnd,sizeof(nSnd));
setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nSnd,sizeof(nSnd));
SetSockOpt(s,IPPROTO_TCP,TCP_NODELAY,(const char*)&bNodelayt,sizeof(BOOL));*/
改为我说的(因为你数据只有1K左右):
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));
setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));
2.修改处理I/O的代码,如果你是UNIX ,LINUIX,平台,立即改为select()模型
判断是否有数据可读;如果是WIN32 平台,改为overlapped+WSAeventselect 或者
是IOCP(完成端口)
对于第1点,我试过,改动没有效果;
对于第2点,因为我要控制每个信道的传输,不能太饱,也不能太饿,而采用select()模型我不便于控制。因此没有采用select模式,还请gdy119(夜风微凉) 兄继续指教,谢谢!
//设置非阻塞方式连接
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
if(ret==SOCKET_ERROR)return 0;
如果是,但后面你用了:
for(;;)
{
p=first;
while(p=p->next)
{
p->sock.recvfrom(...);
bool bsend= ......//根据接收的命令数据判断是否需要发送
if(bsend)
{
p->sock.sendto(...);
}
}
}
这个阻塞模式的接受数据的方式,不是自相矛盾吗?
你要知道阻塞模式的方式,recv(),或send()不到数据的时候是要将线程挂起的,
浪费的资源和开销是很大的!
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);设置为非阻塞模型的,而且后面用了
个阻塞模式的接受数据的方式。但我考虑是接收不到就直接返回,我不期望每次都收到数据,只是应付终端不定时发来的数据。我不知道“阻塞模式的方式,recv(),或send()不到数据的时候是要将线程挂起的,浪费的资源和开销是很大的!”,recv()不到数据的时候线程会挂起,能具体些吗?你认为我用什么模式来处理更好些呢?再次感谢夜风微凉兄.