我想在localhost上创建Delphi6和Eclipse之间的套接字通信。 Delphi-Code似乎有效,我可以将数据从Delphi-Server发送到Delphi-Client。现在我想将数据从相同的Delphi-Server发送到Java-Client。以下代码我使用了几个例子。似乎已经建立了Delphi和Java之间的连接,但是在while循环(stdIn.readLine())中,程序不再起作用了。没有例外。该程序停止工作。如何从Delphi-server读取数据?
谢谢!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class JavaClientSocketEx {
public static void main(String[] args) {
try {
Socket echoSocket = new Socket("127.0.0.1", 10003);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String userInput;
echoSocket.close();
while ((userInput = stdIn.readLine()) != null) { // at this point the programm doesnt work anymore!
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
编辑:Delphi代码
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, ExtCtrls, StdCtrls;
type
CustomRec = record
Zahl: byte;
end;
TForm1 = class(TForm)
Edit1: TEdit;
Timer1: TTimer;
sendenButton: TButton;
Edit2: TEdit;
ClientSocket1: TClientSocket;
ServerSocket1: TServerSocket;
procedure Timer1Timer(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure sendenButtonClick(Sender: TObject);
procedure ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
senden : boolean;
implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject);
var
text : string;
begin
text := Edit1.Text;
ClientSocket1.Socket.SendText(text);
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
sendenButton.Caption := 'Send';
senden := false;
ClientSocket1.Port := 10003;
ClientSocket1.Host := '127.0.0.1';
ClientSocket1.Active := true;
ServerSocket1.Port := 10003;
ServerSocket1.Active := true;
end;
procedure TForm1.sendenButtonClick(Sender: TObject);
begin
if senden then
begin
senden := false;
sendenButton.Caption := 'Send';
Timer1.Enabled := false;
end
else
begin
senden :=true;
sendenButton.Caption := 'Stopp';
Timer1.Enabled := true;
end;
end;
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode := 0;
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var Rec: CustomRec;
begin
edit2.Text := Socket.ReceiveText;
rec.Zahl:=StrToInt(Edit2.Text);
Socket.SendBuf(Rec,sizeof(Rec));
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode :=0;
end;
end.
在点击" sendenButton"之后,delphi-client开始在一秒间隔内定期发送第一个edit-Element(即输入)的数据。第二个edit-Element是接收数据的输出。在我再次点击此按钮后停止发送。
答案 0 :(得分:4)
问题可能出在while
循环中,您尝试在已经关闭的套接字上进行读写。
echoSocket.close();
while ((userInput = stdIn.readLine()) != null) { // at this point the programm doesnt work anymore!
out.println(userInput);
. . .
这可以通过循环后移动echoSocket.close();
来解决
之后,Java客户端工作;现在问题出在服务器上。
Delphi客户端绑定到服务器并优先于Java服务器 要解决此问题,请禁用Delphi客户端:
//ClientSocket1.Active := true;
之后服务器正常工作。
此时,当您通过控制台发送号码时,请说42
,服务器会引发异常:
项目Project1.exe引发了一个异常类EConvertError,消息为''42
'不是有效的整数值'。
问题出现在ServerSocket1ClientRead
mehod中,并附带此说明:
rec.Zahl := StrToInt(Edit2.Text);
因为sockect收到的字符串是
'42'#$D#$A
您可以考虑清理文本:
rec.Zahl := StrToInt(StringReplace(Trim(Edit2.Text), '''', '', [rfReplaceAll]));
将回复发送到客户端时,消息终结符#$D#$A
丢失。这条线
Socket.SendBuf(Rec, sizeof(Rec));
必须像
一样进行更改Socket.SendText(IntToStr(rec.Zahl) + #13#10);
这解决了阻止客户端问题。
已编辑的程序如下 - 我已将逻辑从OnActivate
移至OnCreate
表单事件:
Delphi服务器/客户端
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, ExtCtrls, StdCtrls;
type
CustomRec = record
Zahl: Byte;
end;
TForm1 = class(TForm)
Edit2: TEdit;
Edit1: TEdit;
sendenButton: TButton;
procedure ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure FormCreate(Sender: TObject);
procedure sendenButtonClick(Sender: TObject);
private
{ Private-Deklarationen }
ClientSocket1: TClientSocket;
ServerSocket1: TServerSocket;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
ClientSocket1 := TClientSocket.Create(Self);
ClientSocket1.OnError := ClientSocket1Error;
ServerSocket1 := TServerSocket.Create(Self);
ServerSocket1.OnClientError := ServerSocket1ClientError;
ServerSocket1.OnClientRead := ServerSocket1ClientRead;
ClientSocket1.Port := 10003;
ClientSocket1.Host := '127.0.0.1';
//ClientSocket1.Open;
ServerSocket1.Port := 10003;
ServerSocket1.Open;
end;
procedure TForm1.sendenButtonClick(Sender: TObject);
begin
sendenButton.Enabled := False;
ClientSocket1.Open;
ClientSocket1.Socket.SendText(Edit1.Text);
ClientSocket1.Close;
sendenButton.Enabled := True;
end;
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode := 0;
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
rec: CustomRec;
sInt, reply: string;
iInt, iCode: Integer;
begin
edit2.Text := Socket.ReceiveText;
sInt := StringReplace(Trim(Edit2.Text), '''', '', [rfReplaceAll]);
Val(sInt, iInt, iCode);
if iCode = 0 then begin
if iInt in [Low(Byte)..High(Byte)] then begin
rec.Zahl := iInt;
reply := IntToStr(rec.Zahl);
end;
end
else
reply := '-1';
Socket.SendText(reply + #13#10);
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode := 0;
end;
end.
Java客户端
public static void main(String[] args) throws UnknownHostException, IOException {
Socket echoSocket = new Socket("127.0.0.1", 10003);
try {
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
//the next 2 lines resume like: if you have to die, die fast
int value = Integer.parseInt(userInput);//ensure that input is an Integer
assert (value >= 0 && value <= 255);// ensure that the Integer is in the Delphi's Byte range
out.println(value);
System.out.println("server replies: " + in.readLine());
}
} finally {
echoSocket.close();
}
}
除了使用writeLine
和readLine
的实现之外,还可以使用DataOutput.writeUTF
和DataInput.readUTF
方法向服务器发送消息并从中读取消息:
Socket echoSocket = new Socket("127.0.0.1", 10003);
OutputStream os = echoSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(os);
out.writeUTF("Hi, it's me!");//your message to the server
InputStream in = echoSocket.getInputStream();
DataInputStream din = new DataInputStream(in);
System.out.println("Server response: " + din.readUTF());
echoSocket.close();
答案 1 :(得分:0)
现在我找到了解决问题的方法。非常感谢你的建议,fantaghirocco,它帮助我找到答案。我似乎不理解服务器 - 客户端架构的原则。我修改了你的代码,现在它对我来说很好。
的Delphi码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, ExtCtrls, StdCtrls;
type
CustomRec = record
Zahl: Byte;
end;
TForm1 = class(TForm)
edit1: TEdit;
ClientSocket1: TClientSocket;
ServerSocket1: TServerSocket;
Label1: TLabel;
procedure ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure MyServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure FormActivate(Sender: TObject);
private
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode := 0;
end;
procedure TForm1.MyServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
rec: CustomRec;
sInt, reply: string;
iInt, errorPos: Integer;
begin
edit1.Text := Socket.ReceiveText;
sInt := StringReplace(Trim(Edit1.Text), '''', '', [rfReplaceAll]);
Val(sInt, iInt, errorPos);
if errorPos = 0 then begin
if iInt in [Low(Byte)..High(Byte)] then begin
rec.Zahl := iInt;
iInt := iInt +1;
reply := IntToStr(rec.Zahl);
end;
end
else
reply := '-1';
reply := 'reply ' + reply + ' accepted';
Socket.SendText(reply + #13#10);
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode := 0;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
ClientSocket1 := TClientSocket.Create(Self);
ClientSocket1.OnError := ClientSocket1Error;
ServerSocket1 := TServerSocket.Create(Self);
ServerSocket1.OnClientError := ServerSocket1ClientError;
ServerSocket1.OnClientRead := MyServerSocket1ClientRead;
ClientSocket1.Port := 10003;
ClientSocket1.Host := '127.0.0.1';
ServerSocket1.Port := 10003;
ServerSocket1.Open;
end;
end.
的Delphi-形式:
Java的代码:
class TCPClient {
private static int input;
public static void main(String[] args) throws UnknownHostException, IOException {
Socket echoSocket = new Socket("127.0.0.1", 10003);
Timer timer = new Timer();
input = 0;
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
input = input +1;
doTime(echoSocket, input);
} catch (IOException e) {
e.printStackTrace();
}
}
}, 1000,1000);
}
private static void doTime(Socket echoSocket, int input) throws IOException {
try {
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
//the next 2 lines resume like: if you have to die, die fast
int value = input;//ensure that input is an Integer
assert (value >= 0 && value <= 255);// ensure that the Integer is in the Delphi's Byte range
System.out.println("sending server reply number : " + value);
out.println(value);
System.out.println("server replies: " + in.readLine());
} finally {
// echoSocket.close();
}
}
}