简体   繁体   中英

Socket Communication between Delphi and Java

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.

在此处输入图片说明

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM