请教一下TClientSocket的问题,请各位高手帮忙(40分)

  • 主题发起人 主题发起人 tscc
  • 开始时间 开始时间
T

tscc

Unregistered / Unconfirmed
GUEST, unregistred user!
我想指定用TClientSocket的固定端口(例如8888)连接到服务器,但是好像TClientSocket的属性中只能指定连接到的地址和端口,不能设置自己的端口,请教一下怎样解决~
 
clientsocket,看名字就知道他是客户端的程序,他不能设置自己的端口
 
你想干什么?

你想用特定的端口连接制定的server端口?

 
to tt8:

是的,我想用特定的客户端口连接到server上
 
概念性错误.
客户端与服务器连接的两个要素:服务器名(IP地址)和端口号;
服务器不开指定端口,客户端怎么连呢?
 
to wz_lizard:

一定可以设置的,因为客户端主动向服务器端连接,肯定是用自己的端口连接
 
确实Client部分可以指定本机的端口和远程服务器的端口通讯,但是用TClientSocket不修改代码的情况下很难实现,用API或者其他控件可以实现,原理就是在connect之前帮定一下
本机端口就OK了。
 
to ludao:

当然是server打开端口,并且有自己的ip
客户端才进行连接,我的目的是客户端用指定的端口进行连接
什么概念性错误~!!!!!!
 
to 张无忌大哥:

久仰你的大名了,我一直非常钦佩,非常感谢你帮忙,有你问题就差不多解决了
能不能说的详细一点呢,最好能帮我找一些资料,谢谢
我的邮箱:cc_tsno1@yahoo.com.cn
 
D7中TClientSocket不能设定本地使用的端口号(请自行看源码验证),如确需使用,请用TServerSocket
 
借寶地一用:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2231392
 
LocalPort是用getsockname查询得到的本地端口号,因此只读的,绑定本地端口的方法如下:

var
SockAddrIn:TSockAddrIn;
begin
ClientSocket1.Open; // 在绑定前需先开启Socket
SockAddrIn.sin_port:=htons(1979); // 绑定到本地端口1979
bind(ClientSocket1.Socket.SocketHandle,SockAddrIn,sizeof(TSockAddrIn)); // 绑定操作
end;


 
楼上的办法不太安全,你可以看即使你这么做了,bind可能返回错误,
因为ClientSocket再Open以后就连接到了服务器,连接状态下端口早
就分配好了,你在bind是要出错的,
 
不会出错,如果不先Open,会提示Socket句柄无效,完整的测试代码如下:

procedure TForm1.TestBind;
var
SockAddrIn: TSockAddrIn;
begin
ClientSocket1.Open;
SockAddrIn.sin_family:=AF_INET;
SockAddrIn.sin_addr.S_addr:=0;
SockAddrIn.sin_port:=htons(1979);
if bind(ClientSocket1.Socket.SocketHandle,SockAddrIn,sizeof(TSockAddrIn))=0 then
ShowMessage('绑定成功!')
else
case GetLastError() of
WSANOTINITIALISED:
ShowMessage('在使用此API之前应首先成功地调用WSAStartup()。');
WSAENETDOWN:
ShowMessage('WINDOWS套接口实现检测到网络子系统失效。');
WSAEADDRINUSE:
ShowMessage('所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。');
WSAEFAULT:
ShowMessage('namelen参数太小(小于sockaddr结构的大小)。');
WSAEINPROGRESS:
ShowMessage('一个阻塞的WINDOWS套接口调用正在运行中。');
WSAEAFNOSUPPORT:
ShowMessage('本协议不支持所指定的地址族。');
WSAEINVAL:
ShowMessage('该套接口已与一个地址捆绑。');
WSAENOBUFS:
ShowMessage('无足够可用缓冲区,连接过多。');
WSAENOTSOCK:
ShowMessage('描述字');
end;
end;
 
我看过VCL代码,你在DoOpen的时候,ClientSocket已经调用了connect,这个时候他的端口
应该绑定了,你在函数后面绑定端口当然没用。即使不出错也不能说他的发数据端口就是
你绑定的端口。
 
我刚才测试过,你的设置端口代码没有起到你说的作用,
procedure TForm1.Button1Click(Sender: TObject);
var
SockAddrIn: TSockAddrIn;
begin
ClientSocket1.Open;
SockAddrIn.sin_family := AF_INET;
SockAddrIn.sin_addr.S_addr := 0;
SockAddrIn.sin_port := htons(1979);
if bind(ClientSocket1.Socket.SocketHandle, SockAddrIn, sizeof(TSockAddrIn)) = 0 then
ShowMessage('绑定成功!')

end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage(IntToStr(Socket.LocalPort));
end;
 
谢谢两位大哥的鼎力帮忙,我去试一下先
 
报错,错误代码为10022,报告bind状态出错,原因是在Open的时候已经连接上了
服务器,在一个已经建立连接的套接字上绑定端口当然要出错
 
测试本地端口应从ServerSocket端读取:
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage(inttostr(Socket.RemotePort));
end;

用netstat命令也可以观察到。
 
Socket.LocalPort也是可以得到本地得端口,不信你可以测试,
 
后退
顶部