【问题标题】:Socket Communication between Delphi and JavaDelphi和Java之间的套接字通信
【发布时间】:2016-01-20 20:58:26
【问题描述】:

我想在本地主机上创建 Delphi6 和 Eclipse 之间的套接字通信。 Delphi-Code 似乎可以工作,我可以将数据从 Delphi-Server 发送到 Delphi-Client。现在我想将数据从同一个 Delphi-Server 发送到 Java-Client。以下代码是我从几个示例中使用的。 Delphi 和 Java 之间的联系似乎已经建立,但是在 while-loop (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 客户端开始以一秒的间隔定期从第一个编辑元素(即输入)发送数据。第二个编辑元素是接收数据的输出。再次单击此按钮后,它停止发送。

【问题讨论】:

  • 您能否用 Delphi 服务器完成您的问题并详细说明 “停止工作” 的概念?我的意思是:发生异常或userInput 立即为null
  • System.in 如果你想输出套接字输入,我觉得很奇怪:BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
  • 也不例外。在“userInput = stdIn.readLine()”行的调试模式下,似乎程序已完成。我也尝试过其他解决方案,例如:javaproblemstips.com/256592。但是在“String str = in.readLine();”也有同样的问题
  • 但是您在等待System.in,而不是在等待套接字,而且在我看来套接字未绑定到System.in,是吗?我不明白两者之间的关系,抱歉=:-)
  • 我知道你的意思,但这也不起作用,当我删除“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()));字符串用户输入; // echoSocket.close(); while ((userInput = in.readLine()) != null) { out.println(userInput); System.out.println("echo:" + in.readLine()); }

标签: java sockets delphi


【解决方案1】:
  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,服务器会引发异常:

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

    问题发生在 ServerSocket1ClientRead 方法中,这条指令:

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

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


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

【讨论】:

  • 和以前一样的问题。调试器显示了这个(图片):fs1.directupload.net/images/150916/ytocuj4u.jpg 好像有一个循环
  • 感谢您的建议 fantaghirocco,但它仍然不起作用。我没有在 Java 中得到任何流。但是delphi和java之间是有联系的。如果我退出 java 程序,delphi 服务器会以“ESocketError 10053”中断。所以我认为代码中仍然存在一个小错误。我只想在不使用文本文件的情况下将数据从 delphi 发送到 java ;) 有人可以帮忙吗?
  • 我很抱歉,但我在 5 个月前粘贴了错误的单位!我用正确的 Delphi 代码再次编辑了答案。重新测试,以上对我有用。用法:1)启动delphi服务器2)启动java客户端3)在java控制台中写入一个数字-回车发送
  • delphi 客户端有一些小问题,但重点是 Delphi-server 和 Java-client 之间的通信
  • 仍然不适合我。遇到异常:在线程“main”中 java.net.ConnectException:连接被拒绝:连接。
【解决方案2】:

现在我找到了解决问题的方法。非常感谢您的建议,fantaghirocco,它帮助我找到了答案。看来我不了解服务器-客户端-架构的原理。我修改了你的代码,现在它对我来说很好。

德尔福代码:

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.

德尔福形式:

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

}

【讨论】:

    猜你喜欢
    • 2012-01-26
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多