Z
zepplin79
Unregistered / Unconfirmed
GUEST, unregistred user!
这个程序主要是想让Server(非阻塞)和Client(阻塞)运行一个协议:大致的格式如下:
hello word100
我的问题主要有3个:
1、ClientSokcet给ServerSocket发信息,如果只是发送hello word,则程序可以很好的工作。但是如果后面再加上别的控制字,如一个byte类型的整数,则程序在跳出
ServerSocket1ClientRead(Sender: TObject;Socket: TCustomWinSocket);这个过程的时候,会出现一个异常 Access Viloation at address。。。
2、如果我的协议头比较长,30到40个字节,是不是不能保证ServerSocket1ClientRead过程一次能接收完毕,我该怎么做?》
3、如果服务器端没有起来,直接ClientSocket.active:=true;时发出现一个异常,我在ClientonError中写了捕捉代码还是不行,后在加入了try excetp还是不行.
程序代码如下
hello word100
我的问题主要有3个:
1、ClientSokcet给ServerSocket发信息,如果只是发送hello word,则程序可以很好的工作。但是如果后面再加上别的控制字,如一个byte类型的整数,则程序在跳出
ServerSocket1ClientRead(Sender: TObject;Socket: TCustomWinSocket);这个过程的时候,会出现一个异常 Access Viloation at address。。。
2、如果我的协议头比较长,30到40个字节,是不是不能保证ServerSocket1ClientRead过程一次能接收完毕,我该怎么做?》
3、如果服务器端没有起来,直接ClientSocket.active:=true;时发出现一个异常,我在ClientonError中写了捕捉代码还是不行,后在加入了try excetp还是不行.
程序代码如下
代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdAntiFreezeBase, IdAntiFreeze, IdTCPServer,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,strutils,
ScktComp;
type
TFormMain = class(TForm)
GroupBox1: TGroupBox;
BtnConnect: TButton;
BtnSend: TButton;
BtnDisconnect: TButton;
GroupBox2: TGroupBox;
BtnStop: TButton;
BtnStart: TButton;
Lblog: TListBox;
EdtHost: TEdit;
EdtPort: TEdit;
EdtData: TEdit;
Button4: TButton;
ServerSocket1: TServerSocket;
ClientSocket1: TClientSocket;
procedure BtnConnectClick(Sender: TObject);
procedure BtnStartClick(Sender: TObject);
procedure BtnStopClick(Sender: TObject);
procedure AddLogEntry();
procedure BtnDisconnectClick(Sender: TObject);
procedure BtnSendClick(Sender: TObject);
procedure ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormMain: TFormMain;
FLogEntry,FReceived:string;
implementation
{$R *.dfm}
procedure TFormMain.BtnConnectClick(Sender: TObject);
begin
Clientsocket1.Address := EdtHost.Text;
ClientSocket1.Port := StrToInt(EdtPort.Text);
try
ClientSocket1.Active := true;
except
on E:exception do
showmessage('服务端没有监听');//这里的异常也不能被捕捉???
end;
end;
procedure TFormMain.BtnStartClick(Sender: TObject);
begin
ServerSocket1.Port := StrToInt(EdtPort.Text);
Serversocket1.Active := True;
if serversocket1.Active=true then
begin
BtnStart.Enabled := False;
BtnStop.Enabled := True;
LbLog.Items.Add('服务器已成功启动!');
end
else
begin
BtnStart.Enabled :=true;
BtnStop.Enabled := false;
LbLog.Items.Add('服务器不能正常启动!');
end;
end;
procedure TFormMain.BtnStopClick(Sender: TObject);
begin
try
Serversocket1.Active := False;
BtnStart.Enabled := True;
BtnStop.Enabled := False;
LbLog.Items.Add('服务器已成功停止!');
except
showmessage('服务器不能正常停止');
end;
end;
procedure TFormMain.AddLogEntry();
begin
LbLog.Items.Add(FLogEntry);
end;
procedure TFormMain.BtnDisconnectClick(Sender: TObject);
begin
ClientSocket1.Active:=false;
LbLog.Items.Add('同主机 ' + EdtHost.Text + ' 的连接已断开!');
BtnConnect.Enabled := True;
BtnSend.Enabled := False;
BtnDisconnect.Enabled := False;
end;
procedure TFormMain.BtnSendClick(Sender: TObject);
var Ptr:pointer;
sendstr:string;
SendStrLen:integer;
begin
SendStr := 'hello word';
SendStrLen:=length(SendStr);
try
GetMem(ptr,11);//申请11个Byte
CopyMemory(Ptr,pchar(sendstr),SendStrLen);//把‘hello word’拷贝到ptr指向的地址,占用10个字节
pbyte(pchar(ptr)+10)^ :=100;//将指针偏移10个字节,指向第11个字节位置,写入byte类型值100
LbLog.Items.Add('客户端发送:' + Sendstr);
ClientSocket1.Socket.SendBuf(ptr,11);//组成一个协议头,发往ServerSocket
FreeMem(ptr);
except
LbLog.Items.Add('发送数据失败!');
ClientSocket1.Active:=false;
LbLog.Items.Add('同主机 ' + EdtHost.Text + ' 的连接已断开!');
BtnConnect.Enabled := True;
BtnSend.Enabled := False;
BtnDisconnect.Enabled := False;
end;//end try
end;//
procedure TFormMain.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
LbLog.Items.Add('From IP: '+socket.RemoteAddress+' 被接纳');
end;
procedure TFormMain.ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
Lblog.Items.Add('正在连接'+Edthost.Text+'....');
end;
procedure TFormMain.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
BtnConnect.Enabled := False;
BtnSend.Enabled := True;
BtnDisconnect.Enabled := True;
end;
procedure TFormMain.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var Ptr ,tempptr:pointer;
begin
if socket.ReceiveLength = 11 then//说明接收完毕
begin
GetMem(Ptr,11);//申请11个字节的内存
socket.ReceiveBuf(Ptr,11);//从Socket读11个字节的内容到ptr指向的内存
copymemory(tempptr,pchar(ptr),10);//从ptr指向的内存中拷贝10个字节n内容赋值给tempptr
EdtData.Text:=Pchar(tempptr);
Lblog.Items.Add(inttostr(pByte(pchar(ptr)+10)^));//进行强制指针类型转换,偏移10个字节指向byte的地址,读出byte的值
Freemem(Ptr);
end
else if socket.ReceiveLength < length(EdtData.Text)then//说明没有接收完毕
begin
//此处不知道如何做??
end;
end;//在执行到这里后,系统提示异常。Access Viloation as Address。。。
procedure TFormMain.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);//此事件不知道为什么没有被触发???
var
StrErr:string;
begin
case ErrorEvent of
eeConnect : StrErr:='不能建立连接';
eeDisconnect : StrErr:='连接被关闭';
eeReceive : StrErr:='接收数据出错';
eeSend : StrErr:='发送数据出错';
eeAccept: StrErr :='连接产生链入错误';
else
StrErr:='连接出错';
end;
ErrorCode:=0;
end;
end.