1) 質問: 両方の while ループが同時に実行されていますか? 私が知りたいのは、sendDATA の while ループが実行されている間、main() メソッドの while ループが実行されていることです。
2) そうでない場合、どうすれば同時に送受信できますか? TFTP を実装する必要があるため、パケットごとに 512 バイトを読み取って送信する必要があります。512 バイトを読み取って送信し、ACK パケットがクライアントから到着するのを待ちます。したがって、着信[0] = 3および着信[1] = intブロック #
着信のブロック番号が送信したものと一致する場合、次のパケットを送信できます。そうでない場合は、前のパケットを送信する必要があります。これを1つのループで実装する方法がわかりません。
私のコード:
package source;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.util.Scanner;
public class Server
{
static String[] errorcodes = {"Not defined", "File not found", "Access violation", "Disk full or allocation exceeded", "Illegal TFTP Operation",
"Unknown transfer ID", "File already exists", "No such user"};
static String FILE = "";
static String MODE = "";
static byte[] outgoing = new byte[512];
static byte[] incoming = new byte[512];
static DatagramSocket socket;
static String clientip;
static int clientport;
public static void main(String[] args) throws Exception
{
socket = new DatagramSocket(13373); // 69 Reserved for TFTP
// Listen for incoming packets
while(true) {
DatagramPacket packet = new DatagramPacket(incoming, incoming.length);
socket.receive(packet);
clientip = packet.getAddress().toString().replace("/", "");
clientport = packet.getPort();
System.out.println(clientport);
if(incoming[0] == 1 || incoming[0] == 2) {
handleRequest(incoming);
}
}
}
// sends DATA opcode = 3 : | opcode | block # | data |
private static void sendDATA() {
outgoing = new byte[512]; // Empty array
try {
ByteBuffer sDATA = ByteBuffer.allocate(516);
// 512 - 2 byte opcode, 2 byte block #, 512 data
DatagramPacket data = new DatagramPacket(outgoing, outgoing.length, InetAddress.getByName(clientip), clientport);
InputStream fis = new FileInputStream(new File(FILE));
int a;
int block = 1;
while((a = fis.read(outgoing,0,512)) != -1)
{
data.setLength(a);
sDATA.put((byte)3);
sDATA.put((byte)block);
sDATA.put(outgoing);
socket.send(data);
if(incoming[0] == 3 && incoming[1] == block)
{
}
}
} catch (Exception e) {
}
}
// Request packet: | opcode | filename | 0 | mode | 0 |
// Upravlja le z WRQ / RRQ opcode
private static void handleRequest(byte[] packet)
{
int opcode = packet[0];
String filename = "";
int offset = 0;
String mode = "";
// Get filename
for(int i = 1; i < packet.length; i++) {
if(packet[i] != 0) {
filename += (char)packet[i];
} else {
offset = i;
break;
}
}
// Get mode
for(int j = offset; j < packet.length; j++) {
if(packet[j] != 0) {
mode += (char)packet[j];
}
}
FILE = filename;
MODE = mode;
if(opcode == 1) {
// Do RRQ
File test = new File(filename);
if(test.exists()) {
sendACK();
} else {
sendERROR(1);
}
} else {
// Do WRQ
File test2 = new File(filename);
if(test2.exists()) {
sendERROR(6);
} else {
sendACK();
}
}
}
// send ACK opcode = 4 : | opcode | block # |
// block 0 -> prvi ACK, odgovor na RRQ/WRQ
// block 1 -> stevilo poslanega bloka, stetje blokov se zacne
// pri 1.
private static void sendACK() {
outgoing = new byte[512];
outgoing[0] = (byte)4;
outgoing[1] = (byte)0;
try {
DatagramPacket ackpacket = new DatagramPacket(outgoing, outgoing.length, InetAddress.getByName(clientip), clientport);
socket.send(ackpacket);
} catch(Exception e) {
}
}
// send ERROR packet opcode = 5 : | opcode | errorcode | msg | 0 |
// General errorcodes: 2
private static void sendERROR(int errorcode) {
ByteBuffer errpack = ByteBuffer.allocate(512);
errpack.put((byte)5); // opcode
errpack.put((byte)errorcode); // errorcode
try {
errpack.put(errorcodes[errorcode].getBytes("US-ASCII")); // msg
errpack.put((byte)0);
outgoing = errpack.array(); // Pack ERROR Packet
DatagramPacket errpacket = new DatagramPacket(outgoing, outgoing.length, InetAddress.getByName(clientip), clientport);
socket.send(errpacket);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}