各位:
大家好,很简单的一个SOCKET的初级问题,是这样的:
如何用TServerSocket和TClientSocket控件来两台机器的发送和接收.
写了一个简单例子,服务端程序如下:
unit U_main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ScktComp, winsock,Mask;type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
Panel1: TPanel;
memo_log: TMemo;
ServerSocket1: TServerSocket;
edt_port: TEdit;
Label3: TLabel;
Memo1: TMemo;
Button3: TButton;
Button4: TButton;
list_client: TListBox;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button4Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
procedure write_memo(note:string); { Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
s:TCustomWinSocket;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin if trim(edt_port.Text)='' then
begin
application.MessageBox('端口号不能为空!','提示',64);
exit;
end; ServerSocket1.Port:=strtoint(edt_port.Text);
try
ServerSocket1.Open;
except end;
button1.Enabled:=false;
button2.Enabled:=true;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
button1.Enabled:=true;
ServerSocket1.Close;
write_memo('关闭监听');
button2.Enabled:=false;
end;procedure TForm1.write_memo(note:string);
var
t_time:string;
begin t_time:=FormatDateTime('yyyy-mm-dd hh:nn:ss',now);
memo_log.Lines.Add(t_time+' :'+note);
end;procedure TForm1.ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('打开监听');
end;procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
mo_note:string;
begin mo_note:=socket.ReceiveText;
if mo_note<>'' then
begin
write_memo('接收客户端信息:'+mo_note);
//socket.SendText('0');
end
else begin
write_memo('接收客户端不对!');
//socket.SendText('-1');
end;
end;procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('断开客户端SOCKET连接:'+inttostr(socket.SocketHandle));
end;procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
s:=socket;
write_memo('来自客户端的SOCKET连接IP为:'+socket.LocalAddress+' 端口号为:'+inttostr(socket.LocalPort));
write_memo('来自客户端的SOCKET连接号:'+inttostr(socket.SocketHandle));
list_client.Items.Add(inttostr(socket.SocketHandle));
end;procedure TForm1.Button4Click(Sender: TObject);
begin
memo1.Lines.Clear;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
try
s.SendText(trim(memo1.Text));
write_memo('向客户端发送信息成功:'+trim(memo1.Text));
except
write_memo('向客户端发送信息失败!'+trim(memo1.Text));
end;end;
end.客户端的程序如下:
unit Un_main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ScktComp;type
Tf_main = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Button1: TButton;
Button2: TButton;
Panel1: TPanel;
memo_log: TMemo;
edt_port: TEdit;
Memo1: TMemo;
Button3: TButton;
Button4: TButton;
Label4: TLabel;
edt_host: TEdit;
ClientSocket1: TClientSocket;
procedure Button1Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button3Click(Sender: TObject);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
procedure write_memo(note:string);
{ Private declarations }
public
{ Public declarations }
end;var
f_main: Tf_main;implementation{$R *.dfm}procedure Tf_main.Button1Click(Sender: TObject);
begin ClientSocket1.Address:=trim(edt_host.Text);
ClientSocket1.Port:=strtoint(edt_port.Text);
try
ClientSocket1.open;
button1.Enabled:=false;
button2.Enabled:=true;
except end;end;procedure Tf_main.write_memo(note: string);
var
t_time:string;
begin t_time:=FormatDateTime('yyyy-mm-dd hh:nn:ss',now);
memo_log.Lines.Add(t_time+' :'+note);
end;procedure Tf_main.Button4Click(Sender: TObject);
begin
memo1.Lines.Clear;
end;procedure Tf_main.ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('正在连接服务器:'+trim(edt_host.Text));
end;procedure Tf_main.Button2Click(Sender: TObject);
begin
try
ClientSocket1.Close;
button1.Enabled:=true;
button2.Enabled:=false;
except end;
end;procedure Tf_main.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('已断开服务器:'+trim(edt_host.Text));
end;procedure Tf_main.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('已成功连上服务器:'+trim(edt_host.Text));
end;procedure Tf_main.Button3Click(Sender: TObject);
begin
try
ClientSocket1.Socket.SendText(trim(memo1.Text));
write_memo('向服务端发送信息成功:'+trim(memo1.Text));
except
write_memo('向服务端发送信息失败!'+trim(memo1.Text));
end;
end;procedure Tf_main.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
mo_note:string;
begin mo_note:=socket.ReceiveText;
if mo_note<>'' then
begin write_memo('接收服务端信息:'+mo_note);
socket.SendText('0');
end
else begin write_memo('接收服务端信息不对!');
socket.SendText('-1');
end;
end;end.运行的时候正常,可问题是我在客户端的接收过程即ClientSocket1Read过程中
可以根据接收的信息,回复服务端成功与否的标志即('0'或'-1')
如: write_memo('接收服务端信息:'+mo_note);
socket.SendText('0');
这样是可以的,可是我在服务端的接收过程即ServerSocket1ClientRead过程中,
却无法这样做,大家也注意到了,在这过程中
write_memo('接收客户端信息:'+mo_note);
//socket.SendText('0');
socket.SendText('0');这句必须要注释掉,否则运行时,客户端一向服务端发信息,
程序就会在socket.SendText('0');中产生死循环,为什么?!!!
我如何在服务端的接收过程中也能正常实现与客户端一样的应答功能呢?这样双方就能象GET一条HTTP请求一样,实现互相应答的功能.
还有在服务端的ServerSocket1ClientConnect过程中,
write_memo('来自客户端的SOCKET连接IP为:'+socket.LocalAddress+' 端口号为:'+inttostr(socket.LocalPort));
本来我是想取得连接服务端的客户机IP的,可socket.LocalAddress取到的却是服务端的地址,怎么办?最后一个问题就是,这个例子只能实现两台机子的交互,如何实现多方交互呢(偶初学SOCKET)?
各位达人,请帮忙,万分感谢,分不是问题.
大家好,很简单的一个SOCKET的初级问题,是这样的:
如何用TServerSocket和TClientSocket控件来两台机器的发送和接收.
写了一个简单例子,服务端程序如下:
unit U_main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ScktComp, winsock,Mask;type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
Panel1: TPanel;
memo_log: TMemo;
ServerSocket1: TServerSocket;
edt_port: TEdit;
Label3: TLabel;
Memo1: TMemo;
Button3: TButton;
Button4: TButton;
list_client: TListBox;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button4Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
procedure write_memo(note:string); { Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
s:TCustomWinSocket;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin if trim(edt_port.Text)='' then
begin
application.MessageBox('端口号不能为空!','提示',64);
exit;
end; ServerSocket1.Port:=strtoint(edt_port.Text);
try
ServerSocket1.Open;
except end;
button1.Enabled:=false;
button2.Enabled:=true;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
button1.Enabled:=true;
ServerSocket1.Close;
write_memo('关闭监听');
button2.Enabled:=false;
end;procedure TForm1.write_memo(note:string);
var
t_time:string;
begin t_time:=FormatDateTime('yyyy-mm-dd hh:nn:ss',now);
memo_log.Lines.Add(t_time+' :'+note);
end;procedure TForm1.ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('打开监听');
end;procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
mo_note:string;
begin mo_note:=socket.ReceiveText;
if mo_note<>'' then
begin
write_memo('接收客户端信息:'+mo_note);
//socket.SendText('0');
end
else begin
write_memo('接收客户端不对!');
//socket.SendText('-1');
end;
end;procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('断开客户端SOCKET连接:'+inttostr(socket.SocketHandle));
end;procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
s:=socket;
write_memo('来自客户端的SOCKET连接IP为:'+socket.LocalAddress+' 端口号为:'+inttostr(socket.LocalPort));
write_memo('来自客户端的SOCKET连接号:'+inttostr(socket.SocketHandle));
list_client.Items.Add(inttostr(socket.SocketHandle));
end;procedure TForm1.Button4Click(Sender: TObject);
begin
memo1.Lines.Clear;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
try
s.SendText(trim(memo1.Text));
write_memo('向客户端发送信息成功:'+trim(memo1.Text));
except
write_memo('向客户端发送信息失败!'+trim(memo1.Text));
end;end;
end.客户端的程序如下:
unit Un_main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ScktComp;type
Tf_main = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Button1: TButton;
Button2: TButton;
Panel1: TPanel;
memo_log: TMemo;
edt_port: TEdit;
Memo1: TMemo;
Button3: TButton;
Button4: TButton;
Label4: TLabel;
edt_host: TEdit;
ClientSocket1: TClientSocket;
procedure Button1Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button3Click(Sender: TObject);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
procedure write_memo(note:string);
{ Private declarations }
public
{ Public declarations }
end;var
f_main: Tf_main;implementation{$R *.dfm}procedure Tf_main.Button1Click(Sender: TObject);
begin ClientSocket1.Address:=trim(edt_host.Text);
ClientSocket1.Port:=strtoint(edt_port.Text);
try
ClientSocket1.open;
button1.Enabled:=false;
button2.Enabled:=true;
except end;end;procedure Tf_main.write_memo(note: string);
var
t_time:string;
begin t_time:=FormatDateTime('yyyy-mm-dd hh:nn:ss',now);
memo_log.Lines.Add(t_time+' :'+note);
end;procedure Tf_main.Button4Click(Sender: TObject);
begin
memo1.Lines.Clear;
end;procedure Tf_main.ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('正在连接服务器:'+trim(edt_host.Text));
end;procedure Tf_main.Button2Click(Sender: TObject);
begin
try
ClientSocket1.Close;
button1.Enabled:=true;
button2.Enabled:=false;
except end;
end;procedure Tf_main.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('已断开服务器:'+trim(edt_host.Text));
end;procedure Tf_main.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
write_memo('已成功连上服务器:'+trim(edt_host.Text));
end;procedure Tf_main.Button3Click(Sender: TObject);
begin
try
ClientSocket1.Socket.SendText(trim(memo1.Text));
write_memo('向服务端发送信息成功:'+trim(memo1.Text));
except
write_memo('向服务端发送信息失败!'+trim(memo1.Text));
end;
end;procedure Tf_main.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
mo_note:string;
begin mo_note:=socket.ReceiveText;
if mo_note<>'' then
begin write_memo('接收服务端信息:'+mo_note);
socket.SendText('0');
end
else begin write_memo('接收服务端信息不对!');
socket.SendText('-1');
end;
end;end.运行的时候正常,可问题是我在客户端的接收过程即ClientSocket1Read过程中
可以根据接收的信息,回复服务端成功与否的标志即('0'或'-1')
如: write_memo('接收服务端信息:'+mo_note);
socket.SendText('0');
这样是可以的,可是我在服务端的接收过程即ServerSocket1ClientRead过程中,
却无法这样做,大家也注意到了,在这过程中
write_memo('接收客户端信息:'+mo_note);
//socket.SendText('0');
socket.SendText('0');这句必须要注释掉,否则运行时,客户端一向服务端发信息,
程序就会在socket.SendText('0');中产生死循环,为什么?!!!
我如何在服务端的接收过程中也能正常实现与客户端一样的应答功能呢?这样双方就能象GET一条HTTP请求一样,实现互相应答的功能.
还有在服务端的ServerSocket1ClientConnect过程中,
write_memo('来自客户端的SOCKET连接IP为:'+socket.LocalAddress+' 端口号为:'+inttostr(socket.LocalPort));
本来我是想取得连接服务端的客户机IP的,可socket.LocalAddress取到的却是服务端的地址,怎么办?最后一个问题就是,这个例子只能实现两台机子的交互,如何实现多方交互呢(偶初学SOCKET)?
各位达人,请帮忙,万分感谢,分不是问题.
网上应该比较多
谢谢,你说的很对,而且按你说的前两个问题都已经解决.
就是最后一个问题即
多方交互:简单点就是通过服务器程序转发,在发送的信息中包含目标地址,可以用文本,也可以自定义消息结构。
--------------------------------------
如何实现?能否写个简单的例子.
原先的服务端中有个全局变量即s:TCustomWinSocket;在接收客户端连接的过程即
ServerSocket1ClientConnect中,通过s:=socket;将其附值,可是在多方交互时,
这个socket只能是最新连接上服务器的客户端的socket,这样其它前面连接上服务器的客户端就
无法与服务端通信了(可以发送信息给服务端但收不到服务端发的信息).
跟猴子摘桃一样(只留下了最后一个).
如何解决?希望写一个简单的例子.(最好是双方都只用文本来发送,比较好理解)
万分感谢.
ServerSocket1ClientConnect中,通过s:=socket;将其附值,可是在多方交互时,
这个socket只能是最新连接上服务器的客户端的socket,这样其它前面连接上服务器的客户端就
无法与服务端通信了(可以发送信息给服务端但收不到服务端发的信息).
跟猴子摘桃一样(只留下了最后一个).
如何解决?
///////////////////////////////////////////////////////
你的服务端不用全局变量,因为在TServerSocket中能够得到所有连接的客户端,
ServerSocket1.Socket.ActiveConnections
//////////为所有连接的数量
ServerSocket1.Socket.Connections[i]
//////////为所有的连接,每一个Connections都是一个TCustomWinSocket
--------------------------------------
如何实现?/////////////////////////////////////
譬如在你的发送地方:
ClientSocket1.Socket.SendText(trim(memo1.Text));
-------------------->>>>>>>>>>>>>>>>
ClientSocket1.Socket.SendText('ip:192.168.0.1,text:'+trim(memo1.Text));
//////////指定发送到目的地:192.168.0.1,如果一台电脑上可能运行2个以上的客户端,还需把端口写入。方法一样。
/////////////////
在你的服务端:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
strDestIp:string;
i:integer;
..... mo_note:=socket.ReceiveText;////////内容为ip:192.168.0.1,text:
strDestIp:=Copy(mo_note,4,pos(',text',mo_note)-4);////得到目的地址
for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do
begin
if ServerSocket1.Socket.Connections[i].RemoteHost=strDestIp then/////判断服务端的所有客户端有没有IP地址为该目的地址的
begin
ServerSocket1.Socket.Connections[i].SendText(Copy(mo_note,pos(',text',mo_note)+6,length(mo_note)));
break;
end;
end
end;
//////////指定发送到目的地:192.168.0.1,如果一台电脑上可能运行2个以上的客户端,还需把端口写入。方法一样。指定发送到目的地:192.168.0.1应该为客户端的IP吧。对了,最后一问:SOCKET中用流机制来发还是用字符数据来发?哪个好,更实用?