200分请求大虾们帮忙!! ( 积分: 200 )

  • 主题发起人 主题发起人 Michael790819
  • 开始时间 开始时间
M

Michael790819

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在在做一个关于Tcp/Ip通讯的项目,1个服务端,150个客户端。客户端需要频繁的向服务端发送指令,服务端收到以后,作相应的处理,并返回相应的指令!我现在用的是TcpServer和TcpClient组件,使用的是阻塞模式。但是一旦客户端并发发送指令的时候会造成服务器CPU达到100%,然后就无法再进行通讯了。原因好像是因为端口堵塞了,只有当程序关掉再重新启动的时候,通讯才能继续!
请大虾们指点迷津:
1、这是什么原因引起的?
2、通讯量要求,客户端1秒钟内可以累计发送60个命令,Socket通讯是否支持?
3、最好能给我写个小程序,服务端+客户端!
我的邮箱是:Michael790819@163.com
定当重谢!
 
我现在在做一个关于Tcp/Ip通讯的项目,1个服务端,150个客户端。客户端需要频繁的向服务端发送指令,服务端收到以后,作相应的处理,并返回相应的指令!我现在用的是TcpServer和TcpClient组件,使用的是阻塞模式。但是一旦客户端并发发送指令的时候会造成服务器CPU达到100%,然后就无法再进行通讯了。原因好像是因为端口堵塞了,只有当程序关掉再重新启动的时候,通讯才能继续!
请大虾们指点迷津:
1、这是什么原因引起的?
2、通讯量要求,客户端1秒钟内可以累计发送60个命令,Socket通讯是否支持?
3、最好能给我写个小程序,服务端+客户端!
我的邮箱是:Michael790819@163.com
定当重谢!
 
换用UDP好些。
 
我使用了多线程,但是还是不能解决实际问题!服务器CPU还是会达到100%,通讯中断!
请给我成熟的Demo!
 
问题解决的话,再加500分!!!!很急!!!
 
大虾们都去干嘛了!救命啊!!!
 
用SockesServer做服务不知道你试过了没有?
 
你的服务器什么配置
用非阻塞方式不可以吗
还有就是如果服务器和客户端在一个网段的话,使用UDP情况可能会好一些
如果这两种方式还是不行的话
你应该检查一下你的服务器
是不是设计有问题
并发访问时是不是有资源冲突
造成程序死锁了
 
服务器2.4 内存1G
我给出我的代码,请帮忙看看:
unit untMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Sockets, IdTCPConnection, IdTCPClient, IdBaseComponent,
IdComponent, IdTCPServer, StdCtrls, uReceiveThread, uSendThread, ExtCtrls;

type
TfrmMain = class(TForm)
edtSendNum: TEdit;
lbl1: TLabel;
edtReceiveNum: TEdit;
lbl2: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
CS: TRTLCriticalSection;
ReceiveThread: TReceiveThread;
SendThread: TSendThread;
public
{ Public declarations }
end;

var
ComandList: TStringList;
frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
begin
//
InitializeCriticalSection(CS); //初始化临界区
ComandList := TStringList.Create;
ReceiveThread := TReceiveThread.Create(False); //建立接收线程
SendThread := TSendThread.Create(False); //建立发送线程

end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ComandList.Free;

end;

end.
-------------------------------
unit uReceiveThread; //用于监听端口,接收客户端命令

interface

uses
Classes, Sockets, Windows, Forms, SysUtils;

var
CS:TRTLCriticalSection; //定义临界区

type
TReceiveThread = class(TThread)
private
{ Private declarations }
TcpServer: TTcpServer; //监听和接收信息
procedure OnAccept(Sender: TObject; ClientSocket: TCustomIpClient);
procedure UpdateCaption;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
end;

implementation
uses untMain;

{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure TReadThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ TReadThread }

constructor TReceiveThread.Create(CreateSuspended: Boolean);
begin
FreeOnTerminate := True;
inherited Create(CreateSuspended);

end;

procedure TReceiveThread.Execute;
begin
InitializeCriticalSection(CS); //初始化临界区
TcpServer := TTcpServer.Create(nil); //创建TcpServer
TcpServer.LocalPort := '8990';
TcpServer.LocalHost := '192.168.1.7';
TcpServer.Active := True;
TcpServer.OnAccept := OnAccept;
{ Place thread code here }
end;

procedure TReceiveThread.OnAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
begin
with ClientSocket do
begin
EnterCriticalSection(CS);
try

ComandList.Add(ClientSocket.RemoteHost+'='+ClientSocket.Receiveln());
Synchronize(UpdateCaption);
finally
LeaveCriticalSection(CS);
end;

end;

end;

procedure TReceiveThread.UpdateCaption;
begin
frmMain.edtReceiveNum.Text := IntToStr(StrToInt(frmMain.edtReceiveNum.Text)+1);
end;

end.
----------------------------------
unit uSendThread; //用于打包向客户端发送命令

interface

uses
Classes, Sockets, Windows, SysUtils;

var
CS:TRTLCriticalSection; //定义临界区

type
TSendThread = class(TThread)
private
{ Private declarations }
TCPClient: TTCPClient;
procedure UpdateCaption;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
end;

implementation
uses untMain;

{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure TSendThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ TSendThread }

constructor TSendThread.Create(CreateSuspended: Boolean);
begin
FreeOnTerminate := True;
InitializeCriticalSection(CS); //初始化临界区
TCPClient := TTCPClient.Create(nil); //创建TcpServer
inherited Create(CreateSuspended);

end;

procedure TSendThread.Execute;
const
WAIT_TIME=100;
var
sComand: string;
Count: Integer;
begin
while (WaitForSingleObject(Handle, WAIT_TIME) = WAIT_OBJECT_0) or (not Terminated) do
begin
EnterCriticalSection(CS);
try
Count := ComandList.Count;
if ComandList.Count>0 then
begin
sComand := ComandList.Names[0];
ComandList.Delete(0);
end;
finally
LeaveCriticalSection(CS);
end;

if Count>0 then
with TCPClient do
begin
RemoteHost := sComand;
RemotePort := '8989';
try
if Connect then
begin
//命令处理区
Sendln('LOGON');
//EnterCriticalSection(CS);
try
//frmMain.edtSendNum.Text := IntToStr(StrToInt(frmMain.edtSendNum.Text)+1);
Synchronize(UpdateCaption);
finally
//LeaveCriticalSection(CS);
end;
end;
finally
Disconnect;
end;
end;

end;
{ Place thread code here }
end;

procedure TSendThread.UpdateCaption;
begin
frmMain.edtSendNum.Text := IntToStr(StrToInt(frmMain.edtSendNum.Text)+1);

end;

end.

请给出详细答案!!!!
 
不知道你在什么环境下写的这段代码
不过你要是决定把这个写好的话
这个分给我留着吧
我要定了
首先我提示一点
你先检查一下发送部分的Sendln函数
你确定发送数据不会出错吗
把它加入Try{}except end 结构中判断一下出错情况
还有就是Winsock的Send函数如果缓冲区满了,会出问题
你的代码并没有判断函数的返回值
 
Mike1234567890:我们可以交个朋友,请给予指点!
最好是能够直接优化我的代码,项目确实非常的急,万分感激!
 
Michael790819:
我在论坛发言只是闲来无事
挣点分罢了
你说的这个问题刚好我去年遇到过
我当时不只是急
而且我提出的方案很多人都不赞成
但是实际运行起来确很效
不会丢数,当然是在我的使用中
不过你的应用应该一样不会丢数
你可以在线,一样一样的来测试完成
 
Mike1234567890:我已经按照你的提示去处理了,经过测试sendln()函数并没有抛出异常,堵塞之后,connect已经连接不上了。
请求留下你的联系方式!这个项目马上就要正式用了,万分紧急!
请千万帮帮忙!!
我的邮箱是:Michael790819@163.com
 
连接不上?
你在服务器端怎么设置的
是不是限制最大连接数了
如果设置了,那你就把它加大一点
如果是操作系统限制的
就把总体结构稍改一下
 
我的MSN是rhdmmp@hotmail.com
请加我好吗?定当重谢!这样问答需要很长的时间,我真的很急,请帮帮我!!
 
我没有设置连接数啊。都是默认的。
 
你留QQ吧
我不用MSN的
那你就测试一下同时连接服务器
看看最多能连接多少客户端
 
我的QQ是24503686,请加我!
 
用indy的IDTcpClient和IDTcpServer可能好点
 
后退
顶部