局域网中异步传递信息可用实例(大富翁中找到的源代码不同程度上存在错误,无法使用)(0分)

  • 主题发起人 主题发起人 kyq
  • 开始时间 开始时间
K

kyq

Unregistered / Unconfirmed
GUEST, unregistred user!
以下是局域网中异步传递信息可用实例<br>(大富翁中找到的源代码不同程度上存在错误,无法使用):<br><br>以下代码未处理退出时检查是否仍在发送的问题。<br><br>设Form1中有Memo1, Button1两个控件。<br><br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, StdCtrls, SendNetMessageImpl;<br><br>type<br>&nbsp; TForm1 = class(TForm, ISendNetMessageCallback)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Memo1: TMemo;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; procedure OnSendNetMessageComplete(const Succeeded: Boolean; const<br>&nbsp; &nbsp; &nbsp; FromComputer, ToComputer, FromName, Text: string);<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br><br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>&nbsp; SendNetMessage(Self, 'andy', 'andy1', 'kyq', 'OK123中文321');<br>&nbsp; SendNetMessage(Self, 'andy', 'andy', 'kyq', 'OK123中文321');<br>&nbsp; SendNetMessage(Self, 'andy', 'andy2', 'kyq', 'OK123中文321');<br>end;<br><br>procedure TForm1.OnSendNetMessageComplete(const Succeeded: Boolean;<br>&nbsp; const FromComputer, ToComputer, FromName, Text: string);<br>begin<br>&nbsp; if Succeeded then<br>&nbsp; &nbsp; Memo1.Lines.Append(<br>&nbsp; &nbsp; &nbsp; Format(<br>&nbsp; &nbsp; &nbsp; 'Succeeded in sending message to %s',<br>&nbsp; &nbsp; &nbsp; [ToComputer]<br>&nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; )<br>&nbsp; else<br>&nbsp; &nbsp; Memo1.Lines.Append(<br>&nbsp; &nbsp; &nbsp; Format(<br>&nbsp; &nbsp; &nbsp; 'Failed in sending message to %s',<br>&nbsp; &nbsp; &nbsp; [ToComputer]<br>&nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; );<br>end;<br><br>end.<br><br><br>unit SendNetMessageImpl;<br><br>interface<br><br>type<br>&nbsp; ISendNetMessageCallback = interface<br>&nbsp; &nbsp; procedure OnSendNetMessageComplete(const Succeeded: Boolean; const<br>&nbsp; &nbsp; &nbsp; FromComputer, ToComputer, FromName, Text: string);<br>&nbsp; end;<br><br>procedure SendNetMessage(const SendNetMessageCallback: ISendNetMessageCallback;<br>&nbsp; const FromComputer, ToComputer, FromName, Text: string);<br><br>implementation<br>uses<br>&nbsp; Classes;<br><br>function NetMessageBufferSend(ServerName: PWideChar;<br>&nbsp; MsgName: PWideChar;<br>&nbsp; FromName: PWideChar;<br>&nbsp; Buf: PWideChar;<br>&nbsp; BufLen: integer): Integer; stdcall;<br>&nbsp; external 'netapi32.dll'<br><br>type<br>&nbsp; TTrdSendNetMessage = class(TThread)<br>&nbsp; protected<br>&nbsp; &nbsp; _Succeeded: Boolean;<br><br>&nbsp; &nbsp; _SendNetMessageCallback: ISendNetMessageCallback;<br>&nbsp; &nbsp; _FromComputer, _ToComputer, _FromName, _Text: string;<br><br>&nbsp; &nbsp; procedure Execute; override;<br><br>&nbsp; &nbsp; procedure InvokeCallback;<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create(const SendNetMessageCallback: ISendNetMessageCallback;<br>&nbsp; &nbsp; &nbsp; const FromComputer, ToComputer, FromName, Text: string);<br>&nbsp; end;<br><br>&nbsp; { TTrdSendNetMessage }<br><br>constructor TTrdSendNetMessage.Create(<br>&nbsp; const SendNetMessageCallback: ISendNetMessageCallback;<br>&nbsp; const FromComputer, ToComputer, FromName, Text: string<br>&nbsp; );<br>begin<br>&nbsp; Assert(SendNetMessageCallback &lt;&gt; nil);<br><br>&nbsp; _SendNetMessageCallback := SendNetMessageCallback;<br><br>&nbsp; _FromComputer := FromComputer;<br>&nbsp; _ToComputer := ToComputer;<br>&nbsp; _FromName := FromName;<br>&nbsp; _Text := Text;<br><br>&nbsp; FreeOnTerminate := True;<br><br>&nbsp; inherited Create(False);<br>end;<br><br>procedure TTrdSendNetMessage.Execute;<br>&nbsp; function SendNetMessage(<br>&nbsp; &nbsp; const FromComputer, ToComputer, FromName, Text: WideString<br>&nbsp; &nbsp; ): Boolean;<br>&nbsp; begin<br>&nbsp; &nbsp; Result := NetMessageBufferSend(<br>&nbsp; &nbsp; &nbsp; PWideChar(FromComputer),<br>&nbsp; &nbsp; &nbsp; PWideChar(ToComputer),<br>&nbsp; &nbsp; &nbsp; PWideChar(FromName),<br>&nbsp; &nbsp; &nbsp; PWideChar(Text),<br>&nbsp; &nbsp; &nbsp; Length(Text) * SizeOf(PWideChar)<br>&nbsp; &nbsp; &nbsp; ) = 0;<br>&nbsp; end;<br>begin<br>&nbsp; _Succeeded := SendNetMessage(<br>&nbsp; &nbsp; _FromComputer,<br>&nbsp; &nbsp; _ToComputer,<br>&nbsp; &nbsp; _FromName,<br>&nbsp; &nbsp; _Text<br>&nbsp; &nbsp; );<br><br>&nbsp; Synchronize(InvokeCallback);<br>end;<br><br>procedure TTrdSendNetMessage.InvokeCallback;<br>begin<br>&nbsp; _SendNetMessageCallback.OnSendNetMessageComplete(<br>&nbsp; &nbsp; _Succeeded,<br>&nbsp; &nbsp; _FromComputer,<br>&nbsp; &nbsp; _ToComputer,<br>&nbsp; &nbsp; _FromName,<br>&nbsp; &nbsp; _Text<br>&nbsp; &nbsp; );<br>end;<br><br>procedure SendNetMessage(const SendNetMessageCallback: ISendNetMessageCallback;<br>&nbsp; const FromComputer, ToComputer, FromName, Text: string);<br>begin<br>&nbsp; TTrdSendNetMessage.Create(<br>&nbsp; &nbsp; SendNetMessageCallback,<br>&nbsp; &nbsp; FromComputer,<br>&nbsp; &nbsp; ToComputer,<br>&nbsp; &nbsp; FromName,<br>&nbsp; &nbsp; Text<br>&nbsp; &nbsp; );<br>end;<br><br>end.
 
如果要同步发送,直接使用下面的代码就可以了:<br><br>function NetMessageBufferSend(ServerName: PWideChar;<br>&nbsp; MsgName: PWideChar;<br>&nbsp; FromName: PWideChar;<br>&nbsp; Buf: PWideChar;<br>&nbsp; BufLen: integer): Integer; stdcall;<br>&nbsp; external 'netapi32.dll'<br><br>function SendNetMessage(<br>&nbsp; &nbsp; const FromComputer, ToComputer, FromName, Text: WideString<br>&nbsp; &nbsp; ): Boolean;<br>&nbsp; begin<br>&nbsp; &nbsp; Result := NetMessageBufferSend(<br>&nbsp; &nbsp; &nbsp; PWideChar(FromComputer),<br>&nbsp; &nbsp; &nbsp; PWideChar(ToComputer),<br>&nbsp; &nbsp; &nbsp; PWideChar(FromName),<br>&nbsp; &nbsp; &nbsp; PWideChar(Text),<br>&nbsp; &nbsp; &nbsp; Length(Text) * SizeOf(PWideChar)<br>&nbsp; &nbsp; &nbsp; ) = 0;<br>&nbsp; end;<br>
 
kyq,你这里所说的同步与异步是什么意思?<br>还有,你看了我的代码不知有没有看出来,由于NetMessageBufferSend一次最多只能传1000个字左右,<br>所以我在线程中就做了个循环:如果超出1000字,我就自动把它割成1000的倍数的份数,也<br>正是这个处理,才有线程中变量怪异的现象,对这个你有无解决方案?:)
 
还有,我用你这段代码,无法发送成功:<br>如果要同步发送,直接使用下面的代码就可以了:<br><br>function NetMessageBufferSend(ServerName: PWideChar;<br>&nbsp; MsgName: PWideChar;<br>&nbsp; FromName: PWideChar;<br>&nbsp; Buf: PWideChar;<br>&nbsp; BufLen: integer): Integer; stdcall;<br>&nbsp; external 'netapi32.dll'<br><br>function SendNetMessage(<br>&nbsp; &nbsp; const FromComputer, ToComputer, FromName, Text: WideString<br>&nbsp; &nbsp; ): Boolean;<br>&nbsp; begin<br>&nbsp; &nbsp; Result := NetMessageBufferSend(<br>&nbsp; &nbsp; &nbsp; PWideChar(FromComputer),<br>&nbsp; &nbsp; &nbsp; PWideChar(ToComputer),<br>&nbsp; &nbsp; &nbsp; PWideChar(FromName),<br>&nbsp; &nbsp; &nbsp; PWideChar(Text),<br>&nbsp; &nbsp; &nbsp; Length(Text) * SizeOf(PWideChar)<br>&nbsp; &nbsp; &nbsp; ) = 0;<br>&nbsp; end;<br>不知为什么。
 
用这个就可以:<br>function TSendMsgThread.SendMsg(Toh,From,Msg:string):integer;<br>const<br>COPYTRIGHTPLAIN = #13#10+#13#10+'----========================----'+#13#10+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Message was sended by NM Messager Explorer';<br>TRY_SEND_TIMERS = 3;<br>var<br>&nbsp; ToName :array [0..64] of WideChar;<br>&nbsp; WMsgText:array [0..1000] of WideChar;<br>&nbsp; MsgLen,i,tryNum:integer;<br>begin<br>&nbsp; &nbsp; Result := 1;<br>&nbsp; &nbsp; tryNum := 0;<br>&nbsp; &nbsp; for i := 0 to 64 do ToName := #0;<br>&nbsp; &nbsp; for i := Length(Msg)+1 to 1000 do WMsgText := #0;<br>&nbsp; &nbsp; Msg := Msg + COPYTRIGHTPLAIN;<br>&nbsp; &nbsp; StringToWideChar(Toh,ToName,i);<br>&nbsp; &nbsp; StringToWideChar(Msg,WMsgText,i);<br>&nbsp; &nbsp; MsgLen &nbsp;:= &nbsp;Length(Msg) * SizeOf(PWideChar);<br>&nbsp; &nbsp; while (tryNum &lt; 3) and (Result &lt;&gt; 0) do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result := NetMessageBufferSend(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nil,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ToName,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nil,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @WMsgText,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MsgLen);<br>&nbsp; &nbsp; &nbsp; inc(tryNum);<br>&nbsp; &nbsp; &nbsp; //sleep(2000);<br>&nbsp; &nbsp; end;<br>end;<br>
 
还有,这个线程怪变量值的问题也解决了,方法是:<br>1。用你给的函数申明<br>2。给MsgLen<br>就这样,那个SegNum就正常了。真怪。但解决是解决了,就是不知所以然。<br>希望你能回一下帖。
 
1. <br>NET_API_STATUS NetMessageBufferSend(<br>&nbsp; &nbsp; LPTSTR servername, <br>&nbsp; &nbsp; LPTSTR msgname, <br>&nbsp; &nbsp; LPTSTR fromname, <br>&nbsp; &nbsp; LPBYTE buf, <br>&nbsp; &nbsp; DWORD buflen <br>&nbsp; &nbsp;);<br>Delphi声明应该是:<br>function NetMessageBufferSend(ServerName: PWideChar;<br>&nbsp; MsgName: PWideChar;<br>&nbsp; FromName: PWideChar;<br>&nbsp; Buf: PWideChar;<br>&nbsp; BufLen: Integer): Integer; stdcall;<br><br>&nbsp; WINAPI函数NetMessageBufferSend声明有误,应该为stdcall,使用cdecl会造成stack内容混乱。<br>&nbsp; &nbsp;而且BufLen是应传入按字节计算的Buf长度,而不是传引用。<br>&nbsp; &nbsp;你也知道了,你代码中SegNum的值出错不是因为循环,而是函数调用方式错误引致的。<br>&nbsp; &nbsp;具体可查看Delphi帮助,直接查stdcall就可以了。<br><br>2. 至于你我用同步发送这段代码,导致无法发送成功,我也多番测试过,结果都成功。<br>&nbsp; &nbsp;如:<br> 从计算机andy发送到计算机kevin,使用名称kyq,发送内容是OK123。<br>&nbsp; SendNetMessage('andy','kevin','kyq','OK123');<br><br>3. 至于为什么用你找到的代码可以发送成功,原因如下:<br> a. NetMessageBufferSend函数声明中BufLen错误地声明为传引用,例如变量BufLen这时的地址是$1234,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 实际传给NetMessageBufferSend的BufLen的值就是$1234,一般情况下该值都比较大。<br> b. NetMessageBufferSend处理时会检查BufLen的值,如果BufLen大于Buf(Buf以Unicode #0字符结束)的实际长度,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;就忽略BufLen,所以在BufLen足够大的情况下,BufLen可忽略。<br><br><br>总结,WINAPI函数NetMessageBufferSend函数调用方式有误外加原因3.a以及3.b,造成了你的代码运行时的奇怪结果。<br><br>另外,<br>同步就是阻塞当前线程,当前线程需要等操作完成才能继续运行。<br>异步就是不阻塞当前线程,当前线程继续运行,操作完成后会以某种方式通知当前线程(可选)。<br><br>例如你在某个Button的OnClick事件中同步发送消息,窗口就会停顿,直到操作完成才能继续使用,<br>而异步就不会导致这种现象。
 
接受答案了.
 
后退
顶部