gpt4 book ai didi

java - 通过同一个套接字发送多条消息不起作用

转载 作者:行者123 更新时间:2023-12-02 03:02:43 26 4
gpt4 key购买 nike

我正在一个简单的 ftp 服务器上工作,客户端必须向服务器发送多条消息,并且对于每条消息,服务器都会向客户端发送回一个应答。当客户端发送一条消息时,它工作正常并且服务器响应没有任何问题,例如,当客户端发送“用户用户名”时,服务器向客户端发送回“需要密码”。

但是当客户端发送另一条消息“PASS 密码”(使用相同的套接字)时,它不起作用!只有第一个交换有效(对于用户名),当发送第一条消息时,服务器应答没有任何问题,但当它想发送第二条消息(对于密码)时它会阻塞。

请问有人可以帮助我吗?谢谢 !!

这是我的代码:

 @Test
public void testProcessPASS() throws IOException{

Socket socket = new Socket(server.getAddress(), server.getcmdPort());

this.ClientReceiveMessage(socket); // to flush
String cmd = "USER user_test\r\n";
this.ClientSendMessage(socket, cmd);
String anwser = this.ClientReceiveMessage(socket);
assertEquals("Response error.", Constants.MSG_331.replace("\r\n", ""), anwser);

//PROBLEME STARTS HERE :/

String cmd2 = "PASS pass_test\r\n";
this.ClientSendMessage(socket, cmd2);
String anwser2 = this.ClientReceiveMessage(socket);
assertEquals(Constants.MSG_230.replace("\r\n", ""), anwser2);
socket.close();

}


public void ClientSendMessage(Socket skt, String msg) throws IOException{

PrintWriter messageClient = new PrintWriter(new OutputStreamWriter(skt.getOutputStream()),true);
messageClient.println(msg);
messageClient.flush();

}

public String ClientReceiveMessage(Socket skt) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(skt.getInputStream()));
String res = br.readLine() ;
return res;
}

这是服务器代码:

 public class Server implements Runnable {

private ServerSocket cmdserverSocket;
private ServerSocket dataServerSocket;

private boolean running;

public Server() throws IOException {
this.cmdserverSocket = new ServerSocket(1024);
this.dataServerSocket = new ServerSocket(1025);
this.running = false;
}

public boolean isRunning() {
return this.running;
}

public InetAddress getAddress() {
return this.cmdserverSocket.getInetAddress();
}

public int getcmdPort() {
return this.cmdserverSocket.getLocalPort();
}

public int getDataPort() {
return this.dataServerSocket.getLocalPort();
}

public void run() {
// TODO Auto-generated method stub
this.running = true;
System.out.println("server started on port : " + this.getcmdPort());

while (this.running) {
try {
Socket socket = this.cmdserverSocket.accept();
new Thread(new FtpRequest(socket, this.dataServerSocket))
.start();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("server error : " + e.getMessage());
this.running = false;
}
}
}

}

这是处理客户端请求并向客户端发送消息并在新线程上运行的类:

 public class FtpRequest implements Runnable {

private Socket cmdSocket;
private Socket dataSocket;
private BufferedReader cmdBufferedReader;
private DataOutputStream cmdDataOutputStream;
private ServerSocket dataServerSocket;
private boolean anonymous;
private boolean connected;
private String username;
private boolean processRunning;
private String directory;

public FtpRequest(Socket cmds, ServerSocket dts) throws IOException {

this.cmdSocket = cmds;
this.dataServerSocket = dts;
this.cmdBufferedReader = new BufferedReader(new InputStreamReader(
this.cmdSocket.getInputStream()));
this.cmdDataOutputStream = new DataOutputStream(
this.cmdSocket.getOutputStream());
this.anonymous = true;
this.connected = false;
this.username = Constants.ANONYMOUS_USER;
this.processRunning = true;
this.directory = "/home";

}

/**
* send a message on the socket of commands
*
* @param msg
* the msg to send on the socket of commands
* @throws IOException
*/
public void sendMessage(String msg) throws IOException {
System.out.println("FtpRequest sendMessage : " + msg);
PrintWriter messageClient = new PrintWriter(new OutputStreamWriter(
this.cmdDataOutputStream), true);
messageClient.println(msg);
messageClient.flush();

/*
* this.cmdDataOutputStream.writeBytes(msg);
* this.cmdDataOutputStream.flush(); this.cmdSocket.close();
*/
}

public void run() {
// TODO Auto-generated method stub
System.out.println("FtpRequest running ...");
try {
this.sendMessage(Constants.MSG_220); // service ready for new user
this.handleRequest();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // service ready for new user

}

/**
* this method handle the request readen from cmd socket and run the
* required method
*
* @throws IOException
*/
private void handleRequest() throws IOException {

String rqst = this.cmdBufferedReader.readLine();

Request request = new Request(rqst);
System.out.println("FtpRequest handleRequest" + rqst);

switch (request.getType()) {
case USER:
this.processUSER(request);
break;

case PASS:
this.processPASS(request);
break;

default:
this.sendMessage(Constants.MSG_502); // Command not implemented.\r\n
break;

}

/*
* if (this.processRunning = true) this.handleRequest();
*
* else { this.cmdSocket.close(); System.out.println("socket closed ");
* }
*/

}

private void processUSER(Request rqst) throws IOException {

System.out.println("FtpRequest processUSER");
if (rqst.getArgument().equals(Constants.ANONYMOUS_USER)) {
this.sendMessage(Constants.MSG_230); // user loged in
this.connected = true;
this.anonymous = true;
this.username = Constants.ANONYMOUS_USER;
} else if (rqst.getArgument().equals(Constants.USER_TEST)) {
this.sendMessage(Constants.MSG_331); // User name okay, need
// password.\r\n
this.username = Constants.USER_TEST;
} else
this.sendMessage(Constants.MSG_332);
}

private void processPASS(Request rqst) throws IOException {
System.out.println("FtpRequest processPASS");
if (rqst.getArgument().equals(Constants.USER_TEST)
&& rqst.getArgument().equals(Constants.PASS_TEST)) {
this.sendMessage(Constants.MSG_230);
this.connected = true;
this.anonymous = false;
} else
this.sendMessage(Constants.MSG_332); // au cas seulement le mot de
// passe est fourni
}


}

最佳答案

您的代码存在一些问题。

ClientSendMessage() 使用 PrintWriter.println(),它输出换行符。但是您的输入字符串已经有换行符,因此println()正在发送额外的换行符。此外,换行符 println() 输出与平台相关,而 FTP 专门使用 CRLF。所以你根本不应该使用println()

ClientReceiveMessage() 不考虑多行响应。每RFC 959 ,第 4.2 节“FTP 回复”:

A reply is defined to contain the 3-digit code, followed by Space<SP>, followed by one line of text (where some maximum line lengthhas been specified), and terminated by the Telnet end-of-linecode.  There will be cases however, where the text is longer thana single line.  In these cases the complete text must be bracketedso the User-process knows when it may stop reading the reply (i.e.stop processing input on the control connection) and go do otherthings.  This requires a special format on the first line toindicate that more than one line is coming, and another on thelast line to designate it as the last.  At least one of these mustcontain the appropriate reply code to indicate the state of thetransaction.  To satisfy all factions, it was decided that boththe first and last line codes should be the same.   Thus the format for multi-line replies is that the first line   will begin with the exact required reply code, followed   immediately by a Hyphen, "-" (also known as Minus), followed by   text.  The last line will begin with the same code, followed   immediately by Space <SP>, optionally some text, and the Telnet   end-of-line code.      For example:                          123-First line                          Second line                            234 A line beginning with numbers                          123 The last line   The user-process then simply needs to search for the second   occurrence of the same reply code, followed by <SP> (Space), at   the beginning of a line, and ignore all intermediary lines.  If   an intermediary line begins with a 3-digit number, the Server   must pad the front to avoid confusion.

The server's initial greeting is likely to be multi-line, but any response to any command can potentially be multi-line, so you need to handle that.

But more importantly, when doing error checking, you need to look at only the 3-digit response code, not the text that accompanies it. Except for a few select commands, like PASV, MLST/MLSD, etc, the text is otherwise arbitrary, the server can send whatever it wants. So you need to ignore the text except for those cases where it is actually needed, or when reporting error messages to the user.

Try something more like this:

private Socket socket;
private BufferedReader br;

@Test
public void testProcessPASS() throws IOException{

socket = new Socket(server.getAddress(), server.getcmdPort());
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

this.ClientReceiveMessage(220);
this.ClientSendMessage("USER user_test", 331);
this.ClientSendMessage("PASS pass_test", 230);
this.ClientSendMessage("QUIT", 221);

socket.close();

br = null;
socket = null;
}

public int ClientSendMessage(String msg, int ExpectedReplyCode) throws IOException{

Writer bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(msg);
bw.write("\r\n");
bw.flush();

return ClientReceiveMessage(ExpectedReplyCode);
}

public int ClientReceiveMessage(int ExpectedReplyCode) throws IOException{

String line = br.readLine();
String msgText = msgText.substring(4);

if ((line.length() >= 4) && (line[3] == '-')) {
String endStr = line.substring(0, 2) + " ";
do {
line = br.readLine();
msgText += ("\r\n" + line.substring(4));
}
while (line.substring(0, 3) != endStr);
}

int actualReplyCode = Integer.parseInt(line.substring(0, 2));
assertEquals("Response error. " + msgText, ExpectedReplyCode, actualReplyCode);

// TODO: if the caller wants the msgText for any reason,
// figure out a way to pass it back here...

return actualReplyCode;
}

关于java - 通过同一个套接字发送多条消息不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42217340/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com