I want to create a socket-communication between Delphi6 and Eclipse at localhost. The Delphi-Code seems to work, i can send data from Delphi-Server to Delphi-Client. Now i want to send data from same Delphi-Server to Java-Client. Following code i used from several examples. The connection between Delphi and Java seems established, but at the while-loop (stdIn.readLine()) the programm doesnt work anymore. There is no exception. The programm just stops to work. How can i read data from Delphi-server?
Thanks!
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();
}
}
}
edit: Delphi-code
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.
The delphi-client starts to send data form first edit-Element (thats the input) periodicly in one-second-interval after I clicked on "sendenButton". The second edit-Element is the output of the received data. It stops to send, after I clicked this button again.
An issue can be in the while
loop where you are trying to read and write on an already closed socket.
echoSocket.close(); while ((userInput = stdIn.readLine()) != null) { // at this point the programm doesnt work anymore! out.println(userInput); . . .
This can be solved moving the echoSocket.close();
after the loop.
After that the Java client works; now the issue is in the server.
The Delphi client is bound to the server and takes precedence over the Java one.
To solve this, disable the Delphi client:
//ClientSocket1.Active := true;
After that the server works.
At this point, when you send a number through the console, say 42
, the server raises an exception:
Project Project1.exe raised an exception class EConvertError with message ''42
' is not a valid integer value'.
The issue happens in the ServerSocket1ClientRead
mehod with this instruction:
rec.Zahl := StrToInt(Edit2.Text);
Because the string received by the sockect is
'42'#$D#$A
You may consider to sanitize the text:
rec.Zahl := StrToInt(StringReplace(Trim(Edit2.Text), '''', '', [rfReplaceAll]));
When you send the reply to the client, the message terminator #$D#$A
is missing. The line
Socket.SendBuf(Rec, sizeof(Rec));
has to be changed like
Socket.SendText(IntToStr(rec.Zahl) + #13#10);
This solves the blocking client issue.
The edited programs follow - I have moved the logic from the OnActivate
to the OnCreate
form event:
The Delphi server/client
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.
The Java client
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();
}
}
Apart from the implementation which uses the writeLine
and readLine
, a message can be sent to and read from the server using the DataOutput.writeUTF
and DataInput.readUTF
methods:
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();
Now I found a solution for my problem. Thank you very much for your suggestions, fantaghirocco, it helped me to find an answer. It seems I was not understanding the principles of server-client-architecture. I modified your code and now it works fine for me.
Delphi-Code:
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-Form:
Java-Code:
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();
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.