Delphi与Java之间的套接字通信

时间:2015-09-16 08:42:48

标签: java sockets delphi

我想在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是接收数据的输出。在我再次点击此按钮后停止发送。

enter image description here

2 个答案:

答案 0 :(得分:4)

  1. 问题可能出在while循环中,您尝试在已经关闭的套接字上进行读写。

    echoSocket.close();
    while ((userInput = stdIn.readLine()) != null) { // at this point the programm doesnt work anymore!
      out.println(userInput);
      . . .
    

    这可以通过循环后移动echoSocket.close();来解决 之后,Java客户端工作;现在问题出在服务器上。

  2. Delphi客户端绑定到服务器并优先于Java服务器 要解决此问题,请禁用Delphi客户端:

    //ClientSocket1.Active := true;
    

    之后服务器正常工作。

  3. 此时,当您通过控制台发送号码时,请说42,服务器会引发异常:

      

    项目Project1.exe引发了一个异常类EConvertError,消息为''42
      '不是有效的整数值'。

    问题出现在ServerSocket1ClientRead mehod中,并附带此说明:

    rec.Zahl := StrToInt(Edit2.Text);
    

    因为sockect收到的字符串是

    '42'#$D#$A
    

    您可以考虑清理文本:

    rec.Zahl := StrToInt(StringReplace(Trim(Edit2.Text), '''', '', [rfReplaceAll]));
    
  4. 将回复发送到客户端时,消息终结符#$D#$A丢失。这条线

    Socket.SendBuf(Rec, sizeof(Rec));
    

    必须像

    一样进行更改
    Socket.SendText(IntToStr(rec.Zahl) + #13#10);
    

    这解决了阻止客户端问题。

  5. 已编辑的程序如下 - 我已将逻辑从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();
        }            
    }
    

    除了使用writeLinereadLine的实现之外,还可以使用DataOutput.writeUTFDataInput.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-形式:

enter image description here

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

}