为什么出错?高手给指点一下(300分)

  • 主题发起人 主题发起人 wisenow
  • 开始时间 开始时间
W

wisenow

Unregistered / Unconfirmed
GUEST, unregistred user!
1.
// 要在线程里响应消息
// 出现无效句柄错误
unit Unit2;

interface

uses
Classes, Windows, Messages;

type
TMyThread = class(TThread)
FHandle1: THandle;
procedure WinProc(var Msg: TMessage);
function GetHandle: THandle;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy;
property Handle1: THandle read GetHandle;
end;

implementation

{ TMyThread }

constructor TMyThread.Create;
begin
if Handle1 = 0 then
Exit;
end;

destructor TMyThread.Destroy;
begin
if FHandle1 <> 0 then
DeallocateHWnd(FHandle1);
end;

procedure TMyThread.Execute;
begin
inherited;
end;

function TMyThread.GetHandle: THandle;
begin
if FHandle1 = 0 then
FHandle1 := AllocateHwnd(WinProc);
Result := FHandle1;
end;

procedure TMyThread.WinProc(var Msg: TMessage);
begin
try
Dispatch(Msg);
except
if Assigned(ApplicationHandleException) then
ApplicationHandleException(Self);
end;
end;

end.

2. 用TClientSocket和TServerSocket通信时,怎样才能释放SendStream发出去的Stream
在没有Disconnect的情况下,因为我还要接着发送很多内容。

3. 用底层的Socket编程时,当调用WSAAsyncSelect(FSock, Handle, WM_SOCKETMSG, FD_READ);
时为什么我的程序收不到消息, 而另一方发送确实已经执行了, 这些代码有问题吗?
发送代码
A := 'ABCDEFGHIJ';
GetMem(Buf, 10);
FillChar(Buf, 10, A[0]);
SendPacket(Buf, Msg.Socket);
//FreeMem(Buf);
ShowMessage('Send OK');
//-----以下为SendPacket过程-----------
procedure SendPacket(var Buf; Sock: TSocket);
var
R: Longint;
begin
R := Send(Sock, Buf, SizeOf(Buf), 0);
if R = SOCKET_ERROR then
ShowMessage('Send() Error!');
end;
如果谁有热心帮我解决此问题,我发代码过去。感激不尽。
--------------------------------------------------------
这是我到这里的第一贴,还望各位捧场。
 
没人吗?
 
1.你得在TMyThread.Execute建立消息循环啊,tthread.execute是纯虚(抽象)方法,你
inherited它一点用也没有.
你在窗口过程里 Dispatch(Msg)干什么,应该在消息循环里派发消息.
 
至于怎么建立消息循环,看看
TApplication.Run和TApplication.ProcessMessage方法.
 
我想在TMyThread中实现类似

procedure WMMyMessage(var Msg: TMessage); message WM_MYMESSAGE;

这样的消息拦截,然后为一个全局变量赋值,然后在Execute中根据这个全局变量的制作出响应

方法很笨,

to xeen 你所说的方法能否给一最个简单的例子?

谢谢!
 
1、你的线程什么都没有做啊,能得到消息就怪了。
2、已经发送出去的stream是不能被本端释放的,你看看tcp/ip的协议就知道了。
3、要确定handle是否有效,还有网络的原因。
 
to chenxz
1.是, 我的线程什么都没做,但是他出错。
2.如果发出去的Stream不能释放,如果我发送了几百兆的东西岂不是要占用大量的内存了?
3.Handle就是用的窗体的 而且FD_CONNECT可以,网络应该没问题
 
1、应该不会是线程中的execute出的错,你跟踪一下看是在哪里。
2、tcp/ip的缓冲应该没那么大,如果通信底层的缓冲满了,stream是发送不成功的。缓冲的
大小和系统有关,也可以修改,但一般都很小的。
3、直接用select试试。
 
to chenxz
1.在执行完Create后就报错, 无效句柄
2.正是因为不能发那么多内容所以要分开发,然后把发送完的Stream释放掉,但是却不能释放
有什么好的办法吗?
3 我用下面的代码,还是没有反应
var
FDSet: TFDSet;
TimeVal: TTimeVal;
Str: string;
begin
while true do
begin
FD_ZERO(FDSet);
FD_SET(FSock, FDSet);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 500;
if select(0, @FDSet, nil, nil, @TimeVal) > 0 then
begin
ReadPacket(Pointer(str), FSock);
ShowMessage(Str);
Break;
end;
end;
end;

 
最简单的例子:
unit Unit2;

interface

uses
Classes,shellapi,windows,messages;
const
wm_mymessage = wm_user+1;
type

mythread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
procedure mymessagehandler(var msg:tmsg);message wm_mymessage;
end;

implementation

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

Synchronize(UpdateCaption);

and UpdateCaption could look like,

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

{ mythread }

procedure mythread.Execute;
var msg:tmsg;
begin
{ Place thread code here }
while GetMessage(MSG, 0, 0, 0) do begin
if msg.message = wm_mymessage then
mymessagehandler(msg);
end;

end;
procedure mythread.mymessagehandler(var msg:tmsg);
begin
beep(2000,1);
end;

你的自定义消息不属于任何窗口,所以就在消息循环直接处理,不用派发.
发送消息的时候用:postthreadmessage(mythread.threadid,wm_mymessage,0,0);
 
谢谢各位

to xeen
threadid和Form的Handle是否可以同等看待?
 
select的第一个参数错了,这样肯定是没结果的。应该是系统最大的描述字+1。
发送成功的stream可以让接收端来处理,或者关闭掉连接。
 
Select的第一个参数应该没错
select():检查一或多个 Sockets 是否处於可读、可写或错误的状态。

格 式: int PASCAL FAR select( int nfds,
fd_set FAR *readfds,
fd_set FAR *writefds,
fd_set FAR *exceptfds,
const struct timeval FAR *timeout );

参 数: nfds 此参数在此并无作用
readfds 要被检查是否可读的 Sockets
writefds 要被检查是否可写的 Sockets
exceptfds 要被检查是否有错误的 Sockets (*暂无作用)
timeout 此函式该等待的时间。若为 NULL 时,
表示 blocking,此函式会等到有事件发生。

传回值: 成功 - 符合条件的 Sockets 总数 (若 Timeout 发生,则为 0)
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

说明: 使用者可利用此函式来检查 Sockets 是否有资料可被读取,
或是有空间可以写入,或是有错误发生。

-----------------------------------------------
如何在接受端处理,如果断开连接,我要接着传送后续内容还要重新建立连接吗?
速度受影响吗?
 
那你把select的时间定长一点试试,500个微秒太小了。

接收端把所有的stream接收下来就可以释放缓冲区了。
如果socket已经断开,再次发送肯定是要重新建立连接的,在连接时会有一个耗时的操作,
其他的不影响。
 
:)楼主对TCP协议很多地方认识很模糊,
 
to 张无忌,能否给简要、精炼的讲一下TCP协议?
谢谢
 
to chenxz,
//接收端把所有的stream接收下来就可以释放缓冲区了。
我试过好像不行。
 
跟着学习
 
不可能的啦,我觉得你还是看看书先[^]
 
后退
顶部