2

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.

enter image description here

8
  • Can you complete your question with the Delphi server and elaborate the "stops to work" concept? I mean: an exception happens or the userInput is immediately null? Commented Sep 16, 2015 at 8:51
  • System.in seems odd to me if you want to output the socket input: BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in)); Commented Sep 16, 2015 at 9:04
  • Theres no exception. In debug-mode at line "userInput = stdIn.readLine()" it seems like the programm is finished. I've also tried other solutions, like this one: javaproblemstips.com/256592. But there is the same problem at "String str = in.readLine ();" Commented Sep 16, 2015 at 9:08
  • but you are waiting for System.in, not for the socket and it seems to me that the socket isn't bound to System.in, is it? I don't get the relation between the two, sorry =:-) Commented Sep 16, 2015 at 9:11
  • I know what you mean, but this doesnt work either, when i remove "system.in": Socket echoSocket = new Socket("127.0.0.1", 10003); PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader(echoSocket.getInputStream())); String userInput; // echoSocket.close(); while ((userInput = in.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); } Commented Sep 16, 2015 at 9:16

2 Answers 2

4
  1. 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.

  2. 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.

  3. 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]));
    
  4. 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();
Sign up to request clarification or add additional context in comments.

5 Comments

Same problem as before. The debugger shows this (image): fs1.directupload.net/images/150916/ytocuj4u.jpg Seems like the there is a loop
Thanks for your suggestion fantaghirocco, but it still doesnt work. I don't get any stream in Java. But there is a connection between delphi and java. If I quit the java-program, the delphi-server breaks with an "ESocketError 10053". So I think there is still just a little bug inside the code. I only want to send data from delphi to java without using a textfile ;) can somebody help please?
I apologize but I've pasted a wrong unit 5 months ago! I've edited the answer again with the right Delphi code. Re-tested, the above works for me. Usage: 1) start the delphi server 2) start the java client 3) wite a number in the java console - send with carriage return
The delphi client has some minor issues but the point was the communication between the Delphi-server and the Java-client
Still don't working for me. Got an exception: in thread "main" java.net.ConnectException: Connection refused: connect.
-1

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:

enter image description here

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();
    }
}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.