对serversocket和clientsocket用法的疑问!(150分)

  • 主题发起人 主题发起人 coolmyf
  • 开始时间 开始时间
C

coolmyf

Unregistered / Unconfirmed
GUEST, unregistred user!

1.Serversocket的onclientconnect是在clientsocket发出请求时产生,若要使
serversocket拒绝clientsocket的请求,也就是拒绝连接,应该如何操作?

2.serversocket与多个clientsocket建立了连接,如何向其中任一client传送
数据以及响应其中任一clientsocket发送过来的数据呢?一个client与一个
server连接时,可以用响应onclientread事件来操作,那么有多个client同时发
送数据过来时也可以用吗?如不可以,应该如何实现呢?
 
1 就在onclientconnect 中拒绝,不可以吗?
2 初始的 serversocket 专门用来负责监听,和客户建立连接,
建立连接后,产生一个新的 socket,由新的负责和客户的数据交换。
当然后也可以用线程自己实现。
 
1:你最好在 onRead事件里拒绝连接请求,根据收到的用户名和密码来决定是否拒绝他的连接
2:TSeverSocket有一个TList 对象来保存所有的连接,同时一个TServerSocket在非阻塞
模式下同时只能处理一个请求,但是TCP会把其他用户的请求放到TCP堆栈里,下一个FD_READ
消息通知系统有数据要处理,只是你的请求不能太耗时间,不能传输大量数据,一般同时处理
多个请求没有问题,如果想处理多个很耗时间的请求服务,请用阻塞式,前面有很多帖子讨论
这个问题,而且有很多代码可以参考。
 
1:同上
2:不用管,直接用Socket.Send...之类直接操作即可.它会自动建立一个新的SOCKET句柄来处理的
 
客户端最好用线程处理,不过也用不着阻塞式.很容易出问题的.
冰河是这样处理的它只用一个ServerSocket控件来处理服务端和客户端代码分别如下:
// 捕获并发送自己的屏幕图象
void __fastcall TMainForm::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
AnsiString sRecvString = Socket->ReceiveText(); // 保存接收到的字符串
AnsiString sRemoteAddress = Socket->RemoteAddress; // 保存对方IP
int CL,CQ;
u_short port;

// 将接收到的字符串分解为接收端口、色深、品质3个参数
int pos = sRecvString.Pos("/n");
// 接收端口
port = u_short(StrToIntDef(sRecvString.SubString(1,pos-1),0));
sRecvString = sRecvString.SubString(pos+1,sRecvString.Length()-pos);

pos = sRecvString.Pos("/n");
// 色深
CL = StrToIntDef(sRecvString.SubString(1,pos-1),0);
sRecvString = sRecvString.SubString(pos+1,sRecvString.Length()-pos);

pos = sRecvString.Pos("/n");
// 品质
CQ = StrToIntDef(sRecvString.SubString(1,pos-1),0);

if (port)
{
TMemoryStream *ImageStream; // 定义数据流
try
{
ImageStream = new TMemoryStream; // 分配内存
// 捕获当前屏幕并保存到ImageStream中
CaptureImage(CM_ENTIRESCREEN, CL, CQ, ImageStream);
// 发送ImageStream到接收端口
if (!SendStream(sRemoteAddress, port, ImageStream))
MessageBox(0,"发送数据流失败","冰河",MB_ICONERROR);
}
__finally
{
delete ImageStream; // 释放资源
}
}
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ServerSocket1ClientError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
ErrorCode = 0;
MessageBox(0,"远程连接出错","冰河",MB_ICONERROR); // 显示出错信息
}



//---------------------------------------------------------------------------
#include <vcl.h>
#include <jpeg.hpp>
#pragma hdrstop

#include "RecvStream.h"
#include "ChildWin.h"
#include "Socket.cpp"
#include "Ping.cpp"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall TRecvStreamThread::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------
__fastcall TRecvStreamThread::TRecvStreamThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
bool __fastcall TRecvStreamThread::LoadImage(TImage *Image1)
{
CPingReply reply;
CPing PingHost;
bool bRtn = false; // 函数返回值初始为FALSE
StatusBar->SimpleText = "正在连接主机...";
// 先PING主机,检测网络是否畅通
bool rtn = PingHost.Ping(RemoteAddress.c_str(),reply,64,4000,32);
if (rtn)
{
u_short RecvPort=0;
int RecvSocket = BindSocket(&RecvPort); // 动态分配接收端口

if (RecvSocket)
{
// 将接收端口和色深、图象品质合成一条命令,参数之间以'/n'分隔
AnsiString Msg = IntToStr(RecvPort) + "/n" +
IntToStr(CL) + "/n" +
IntToStr(CQ) + "/n";
// 向远程主机发送命令
if (SendMsg(RemoteAddress,LISTENPORT,Msg))
{
TMemoryStream *Stream;
try
{
Stream = new TMemoryStream; // 定义一个数据流并分配内存
StatusBar->SimpleText = "正在接收数据...";
Application->ProcessMessages(); // 处理系统消息
// 开始接收图象到数据流中
if (RecvStream(RecvSocket,Stream))
{
TJPEGImage *jpeg; // 定义JPEG图象
try
{
jpeg = new TJPEGImage; // 分配内存
jpeg->LoadFromStream(Stream); // 从数据流中载入图象
Image1->Picture->Bitmap->Assign(jpeg); // 显示图象
MessageBeep(MB_OK); // 发出提示声音
bRtn = true; // 返回值为TRUE,表示成功
}
__finally
{
delete jpeg; // 释放资源
}
}
else
MessageBox(0,"接收数据流失败","冰河",MB_ICONERROR);
}
__finally
{
delete Stream; // 释放资源
}
}
else
MessageBox(0,("无法与主机'"+ RemoteAddress +"'建立连接").c_str(),
"冰河",MB_ICONERROR);
}
else
MessageBox(0,"分配端口失败,无法继续接收数据","冰河",MB_ICONERROR);
}
else
MessageBox(0,("主机'"+RemoteAddress+"'没有响应").c_str(),"冰河",MB_ICONERROR);

return bRtn;
}

void __fastcall TRecvStreamThread::Execute()
{
//---- Place thread code here ----
if (LoadImage(RemoteScreen))
StatusBar->SimpleText = "数据接收完毕";
else
StatusBar->SimpleText = "接收数据失败";
}
//---------------------------------------------------------------------------
服务端就是单线程而且不是阻塞式的.
 
多人接受答案了。
 
后退
顶部