Socket银行接口,受一堆问题困惑!(高分500) (300分)

  • 主题发起人 主题发起人 seaboy
  • 开始时间 开始时间
S

seaboy

Unregistered / Unconfirmed
GUEST, unregistred user!
我以前没写过Socket程序,现在做与银行的接口时,遇到了以下问题,请各位大虾帮助解决:
基本情况:
银行端: 操作系统为Unix 我方:操作系统为Windows
操作要求:
1. 当银行端发请求报文过来的时候,我方从数据库中读取数据,并返回应答报文给银行方.
2. 我方发请求报文给银行端,银行端取得相关数据,并返回应答报文给我方.
3. 要求我方能同时处理多家银行请求.
问题如下:
1: 我用Delphi中的TServerSocket与TClientSocket能否实现,如果可以有没有其他注意事项?
2: 我写了一个模拟程序,客户端的ClientSocket为ctBlocking方式,服务器端为stThreadBlocking方式,
当客户端发送数据过来时,服务器端马上生成线程,并从数据库中读取数据,然后返回给客户端,但客
户端却无法收到,如果将ClientSocket设为ctNotBlocking方式在OnRead事件中可以读取,但是这样
配对是不好的.有什么办法能读取到服务器端中线程中返回的应答报文.
3. 怎样将ADOConnection传递到服务器的的线程中?
4. 为什么客户端的ClientSocket的SocketHandle与服务器线程中的不同?
5. 为什么在一台机器同时开了两个客户端,后开启的却比前一个开启的前运行结束(完成的工作量相同)?
6. 为什么在一台机器同时开了两个客户端,如果在一个运行之后立即运行另一个,
会发生"连接占线导致另一个命令",如果后一个稍晚运行却不会有这种错误发生?
7. 如果客户端向服务器端发送了大量请求,服务器运行到相对固定值时会中断客户端的连接,
而不会响应OnThreadEnd事件?
8. 如果将客户端程序放到另一台机器运行,服务器端没响应几下就中断了客户端的连接?
9. 各位有这方面经验的都可以谈谈!

其他:
我很急,对于真诚帮忙的大虾或踢一脚的各位都会给分,对给出代码或模型的会加分,
请不要灌水,我不会游泳!
为什么不能超过300分,我可以另外开贴子给分.
 
3. 怎样将ADOConnection传递到服务器的的线程中?
why?你想将你的adoconnection传到银行,让银行帮你更新数据库吗?
 
我也很菜,只能向你推荐一本<<DELPHI6网络编程>>
 
> 3. 怎样将ADOConnection传递到服务器的的线程中?
>why?你想将你的adoconnection传到银行,让银行帮你更新数据库吗?
我是想将ADOConnection传递到线程,在线程中对数据库进行操作!
 
5.这种情况你正常的,线程本来就是后来先完成!
 
我也很感兴趣,帮忙提前。
 
为什么没有回答!
 
这又发一次,分真多,给点俺吧。
问题多多,不好回答,说一些知道的吧。如果你看一个Server: VCL/ScktSrvr.drp,
Client: TSocketConnection,那你会你有些帮助。
2:TClientSocket.ClientType=ctBlocking,要用winsock.select,
或者TWinSocketStream.WaitFor/Read/Write/,或者用SConnect.WSACreateEvent,
WSAEventSelect, WSAResetEvent, WaitFor, WSACloseEvent,因为阻塞,
所以通常是用线程来完成这个东西。像TSocketConnection

3:PostThreadMessage(ThreadID, WM_SOME, 0, Integer(Pointer(ADOCOnnection1));
线程收到信息后,再转: ADOConn := TADOCOnnection(Pointer(msg.lParam));

4:Server.ClientHandle是Accept回来的,不是传过来的,:)

5:听很多人说第一次连接比较慢。:)(可能根你机子的protocol多少也有关,还有一些配置)

6:????

7:OnThreadEnd是在Thread.Free触发,而TSocketServer中的CacheThreadSize中的线程是不会Free,也就是线程Pooling, 它只是线程挂起(suspend),并不是真正Free
8:???
9:什么驴技穷亦
 
本人有非常类似的银行收费接口程序,有空可以与我联系sam_sam_2000@chinaren.com.
 
procedure TFileServerThread.ClientExecute;
var
Data: array[0..1023] of Char;
RecText: string;
SocketStream: TWinSocketStream;
begin
while not Terminated and ClientSocket.Connected do
try
SocketStream := TWinSocketStream.Create(ClientSocket, 5000);
try
FillChar(Data, SizeOf(Data), 0);
if SocketStream.WaitForData(5000) then begin //问题10:这条语名干什么用的?
if SocketStream.Read(Data, SizeOf(Data)) = 0 then
//问题11:如果客户端发了1m的数据,是不是一次性读完?
begin
ClientSocket.Close;
Terminate;
end;
end
else
ClientSocket.Close;

RecText := Data;

if ClientSocket.Connected then
begin
FCallLock.Enter;
try
with FADOStoredProc do begin
ExecProc;
FNow := DateTimeToStr(Parameters.ParamByName('@NetTime').Value);
end;
finally
FCallLock.Leave;
end;

//ClientSocket.SendText(FNow);
SocketStream.Write(Data, StrLen(Data));
Synchronize(UpdateVCL);
end;
finally
SocketStream.Free;
end;
except
HandleException;
end;
end;
 
1、肯定是可以的
2、用常连的工作方式,就是从哪个描述字(sockfd)收到的,就从哪个sockfd返回
4、绝大情况下是不一样的,因为这个是由操作系统来分配的
7、不会
10、这个是socket的接收超时,如果返回是false,则是没有接收到信息,为true则是收到了
11、不一定,接收的数据量跟你接收的容量和tcp/ip的底层工作都有关系
 
10:
if SocketStream.WaitForData(5000) then begin //问题10:这条语名干什么用的?
用来等待数据的到来,如果来了,返回True,没有则等待Timeout/1000秒,时间到了,
也返回为False

当然要全部读完了,不然WaitForData又会马上返回继续读数据了。SocketStream.WaitFor其实
就是用winsocket.select函数,select发现socket的缓冲区中有数据,就马上返回,不然就
等待(timeout)。

SocketStream := TWinSocketStream.Create(ClientSocket, 5000);
try
while not Terminated and ClientSocket.Connected do
//下面行写到上面去,不要一个Loop就生成一个socketStream,完了又Free.
//SocketStream := TWinSocketStream.Create(ClientSocket, 5000);
finally
SocketStream.Free;
end;

还有你在线程中进行数据库的更新不是很好,最好是接收完数据后,通知主线程去做这个处理
将数据的指针发给主线程就完了。
 
谢谢:copy_paste,陈锡震:
>还有你在线程中进行数据库的更新不是很好,最好是接收完数据后,通知主线程去做这个处理
>将数据的指针发给主线程就完了。

这个怎么处理,能否给个模型?

以下是问题12:

TFileServerThread = class(TServerClientThread)
private
FNow: string;
FStringList: TStringList;
FADOConnection: TADOConnection;
FADOStoredProc: TADOStoredProc;
FCallLock: TCriticalSection;

procedure UpdateVCL;
public
constructor Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket);
destructor Destroy; override;

procedure ClientExecute; override;
end;

procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
var
RequestThread: TFileServerThread;
begin
// Create a new thread for connection
RequestThread := TFileServerThread.Create(True, ClientSocket);
RequestThread.FADOConnection.Assign(ADOConnection1);
//问题12: 加上上面一句,程序为什么不会执行.而只能在上面的线程Execute中:
//用FADOConnection := Form1.ADOConnection1;
SocketThread := RequestThread;
Memo1.Lines.Add(Format('---- OnGetThread [%u] ----', [SocketThread.Handle]));
RequestThread.Resume;
end;

继续:
 
procedure MyThread.ClientExecute;
var
s: array [0..1024] of char;
begin
...
Socket.ReciveBuf(@S[0], SizeOf(S));
PostMessage(MainForm.Handle, WM_Some, 0, LongInt(@S[0]));
//可以Integer(Pointer(Object)))
...
end;

//主线程中的消息过程调用是同步的
procedure TMainFOrm.DoSome(var Msg: TMessage); message WM_SOME:
var
S: string;
begin
S := PChar(Pointer(msg.lParam));
DoYourProc(S);
//如果是指针,记得将它Free
end;

12:
在constructor TFileServerThread.Create(True, ClientSocket)构造函数中
有没对它进行构造:
FADOConnection := TADOConnection.Create(nil);
如果用FADOConnection := Form1.ADOConnection1;它只是起对象/指针引用的关系,并没有生成
一个当前线程的对象.当这样在线程中用到FADOConnection,实际上是对Form1.ADOConnection操作,
可能会引起冲突的.应该重新Create new connection,对它的ConnectionString赋值,再连接到数据库中.

还有如果真要在线程中用ADO,好象加入ActiveX.CoInit..., 操作ADO, ActiveX.CoUnInit...函数

FCallLock: TCriticalSection;
临界资源一般在主线程调用中,而不是在线程中生成一个TScriticalSection,这样也没有意义.
多线程中调用主线程的资源,因为可能会多线程访问的冲突,才在主线程中运用TCriticalSection.
而不是在线程中用.

 
这个很感兴趣,提前
 
这个很感兴趣,提前
 
后退
顶部