gpt4 book ai didi

java - 向服务器java发送请求

转载 作者:行者123 更新时间:2023-11-29 05:50:14 26 4
gpt4 key购买 nike

我为服务器和客户端编写了一些代码,用于将文件从服务器传输到客户端,效果非常好;但是我几乎没有问题。我想在 GUI 下构建这段代码,我想列出文件夹中的所有文件,但是如何让客户在看到提供的文件列表后选择他想要的文件(我如何发送一个字符串到服务器以便选择文件)?

服务器代码

import java.io.*;
import java.net.*;



class TCPServer {

public static void listfile(){

File folder = new File("c:/");
File[] listOfFiles = folder.listFiles();

for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
System.out.println("File " + listOfFiles[i].getName());
} else if (listOfFiles[i].isDirectory()) {
System.out.println("Directory " + listOfFiles[i].getName());
}
}
}


public static void main(String args[]) {

listfile();

while (true) {
ServerSocket welcomeSocket = null;
Socket connectionSocket = null;
BufferedOutputStream outToClient = null;

try {
welcomeSocket = new ServerSocket(3248);
connectionSocket = welcomeSocket.accept();
outToClient = new BufferedOutputStream(connectionSocket.getOutputStream());
} catch (IOException ex) {
// Do exception handling
}


if (outToClient != null) {

String FileName = "carexception.java";

File myFile = new File("C:\\"+FileName);

byte[] mybytearray = new byte[(int) myFile.length()];

FileInputStream fis = null;

try {
fis = new FileInputStream(myFile);
} catch (FileNotFoundException ex) {
// Do exception handling
}
BufferedInputStream bis = new BufferedInputStream(fis);

try {
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
outToClient.flush();
outToClient.close();
connectionSocket.close();

// File sent, exit the main method
return;
} catch (IOException ex) {
// Do exception handling
}
}

}
}
}

客户端代码

import java.io.*;
import java.net.*;
import java.util.*;

class TCPClient {

public static void main(String args[]) {
Scanner s = new Scanner(System.in);
byte[] aByte = new byte[1];
int bytesRead;

Socket clientSocket = null;
InputStream is = null;

try {
clientSocket = new Socket("127.0.0.1", 3248);
is = clientSocket.getInputStream();
} catch (IOException ex) {
// Do exception handling
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();

if (is != null) {

FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream("E:\\sss.java");
bos = new BufferedOutputStream(fos);
bytesRead = is.read(aByte, 0, aByte.length);

do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);

bos.write(baos.toByteArray());
bos.flush();
bos.close();
clientSocket.close();
} catch (IOException ex) {
// Do exception handling
}
}
}
}

最佳答案

要完成您所追求的目标,您必须做出很多改变。

您可以假设一个特定的协议(protocol)顺序,在某种意义上,客户端需要向服务器发送请求以便服务器执行任何操作,因此在建立连接时服务器始终处于监听状态。

你应该,

  1. 引入一个发送请求和接收响应的循环
  2. 弄清楚如何发送一个字符串对象
  3. 拆分文件发送部分,这样您就不会分配比操作系统所能提供的更大的字节数组(例如,考虑一个 4GB 的文件,为整个文件分配一个字节数组可能会很麻烦)

所以,考虑到这一点,我们可以开始了。关于步骤 1,这可以使用 while 循环来完成。如果我们假设服务器始终监听请求,则服务器“请求循环”可能看起来像这样。

ClientRequest request;
while (request.getType() != RequestType.Complete) {
// receive new request
// depending on type, send response
}

我们在这里简单地添加了两个类,一个ClientRequest封装了来自客户端的消息,一个枚举RequestType定义了客户端感兴趣的请求类型,例如文件列表或文件内容。

public enum RequestType {
None, Complete, RequestFileList, RequestFileContent
}

public class ClientRequest {
private RequestType type;
public ClientRequest() {
type = RequestType.None;
}

public RequestType getType() {
return type;
}
}

现在我们需要以某种方式将其附加到套接字,因此我们添加了一个接收请求的方法,并将该请求分配给当前请求实例。

ClientRequest request = new ClientRequest();
while (request.getType() != RequestType.Complete) {
// receive new request
receiveRequest(clientSocket.getInputStream(), request);
if (request.getType() != RequestType.Complete) {
// pick a response
}
}

private void receiveRequest(DataInputStream socketStream, ClientRequest request) {
// get a type of request
byte type = socketStream.readByte();
request.setType(RequestType.from(type));
// get parameters for request, depending on type
if (request.getType() == RequestType.RequestFileContent) {
// receive file id (file name for instance, or some other id that you prefer)
String argument = readString(socketStream);
request.setArgument(argument);
}
}

这在 RequestType 中添加了一个 from 方法,将字节转换为请求,在 ClientRequest 中添加了一个 setType 方法,以及一个 readString 方法。我们还在 ClientRequest 中添加了一个新字段和相应的 get 和 set 方法。

public enum RequestType {
// types as before
;
public static RequestType from(byte b) {
switch (b) {
case 1: return RequestType.Complete;
case 2: return RequestType.RequestFileList;
case 3: return RequestType.RequestFileContent;
default: return RequestType.None;
}
}
}

public class ClientRequest {
private String argument;
public void setType(RequestType value) {
type = value;
}

public String getArgument() {
return argument;
}

public void setArgument(String value) {
this.argument = value;
}
}

private String readString(DataInputStream socketStream) {
int length = socketStream.readInt();
byte[] stringBytes = new byte[length];
socketStream.read(stringBytes);
return new String(stringBytes, "UTF-8");
}

现在我们进入下一步,响应请求。只需添加一个 switch case 并处理请求的类型。

{
// depending on type, send response
handleRequest(clientSocket.getOutputStream(), request);
}

private void handleRequest(DataOutputStream socketStream, ClientRequest request) {
switch (request.getType()) {
case RequestType.RequestFileList: {
String[] fileList = getFileList(getCurrentDirectory());
// send response type
socketStream.write(ResponseType.ResponseFileList.getByte());
// send number of files
socketStream.writeInt(fileList.length);
// send each string
for (String fileName : fileList) {
sendString(socketStream, fileName);
}
}
break;
case RequestType.RequestFileContent: {
// send response type ResponseType.ResponseFileContent
// send length of file so other party can determine number of bytes to receive
// send file contents in chunks of a fixed byte array length
// send last part of file contents, if length of file is not evenly divided by array chunk size
}
break;
}
}

sendString 方法只是 readString 方法的“倒序”。

private void sendString(DataOutputStream socketStream, String value) {
int length = value.length();
socketStream.writeInt(length);
byte[] stringBytes = value.getBytes("UTF-8");
socketStream.write(stringBytes);
}

ResponseType 是一个枚举值,类似于 RequestType 中的值,因此客户端可以处理服务器发送的响应类型。

通过这些更改,您将能够请求文件列表并显示服务器发送的文件响应。当用户选择要接收的文件时,客户端可以向服务器发送新的请求,服务器可以将适当的文件内容发送给客户端。

客户端应用程序必须定义一个类似的 ClientRequest 类(可能名称为 ServerResponse),以及服务器指定的用于读取和写入套接字的相应方法溪流。这可以通过将套接字封装在一个类中来进一步抽象,当接收到 GUI 可以订阅的请求或响应时使用监听器模式,..尽管这超出了我的例子。

如果您觉得我需要澄清任何内容,请发表评论,我会尽力回答。

关于java - 向服务器java发送请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14185173/

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