여러 가지 방법으로 문제를 해결하려고했지만 성공하지 못했습니다.이 포럼에서도 정보를 찾았지만 같은 결과를 얻었으니 여기에 나와 있습니다.Java 소켓 동기화 동작
실제로 클라이언트 요청을 받아들이고 서버 (서버)가 특정 폴더에 포함 된 모든 파일을 전송하는 서버 데몬을 수행하고 있습니다. sendFileData (서버에서)와 receiveFileData (클라이언트에서)의 코드를 게시 할 것이다.
서버가 사용하는 다음 receiveFileData 코드에서
public static void receiveFileData(String nombreFichero, Socket s) throws IOException{
File monitored = new File(nombreFichero);
if(monitored.exists() == false){
monitored.createNewFile();
}
byte[] mybytearray;
DataInputStream is = new DataInputStream(s.getInputStream());
FileOutputStream fos = new FileOutputStream(monitored);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = 0;
int hasNext = 1;
do {
bytesRead = is.readInt();//Leo longitud
try {
Thread.sleep(1);// HERE!!!!
} catch (InterruptedException e) {
}
// System.out.println("Bytes read "+bytesRead);
if(bytesRead <= 8187 && bytesRead > 0){
// System.out.println("Bytes leídos "+bytesRead);
hasNext = is.readByte();//Leo si hay más datos por enviar
mybytearray = new byte[bytesRead];
is.read(mybytearray);
if(monitored.exists()){
synchronized(monitored){
bos.write(mybytearray, 0, mybytearray.length);
}
}
mybytearray = null;
}else{
System.out.println("Fuera de rango "+bytesRead);
}
}while(hasNext == 1);
bos.close();
mybytearray = null;
System.out.println("Fichero recibido: "+monitored.getAbsolutePath());
}
, 내가 Thread.sleep를 (1) 또는 System.out을 넣어하지 않는 경우 :
public static void sendFileData(File file, Socket socket) throws FileNotFoundException, IOException, SocketException {
byte[] auxiliar = new byte[8192];
byte[] mybytearray = new byte[(int) file.length()];
int longitud = mybytearray.length;
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
bis.read(mybytearray, 0, longitud);
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
int paquetes = longitud/8187;
int resto = longitud % 8187;
int i = 0;
while(i<paquetes){//The length goes on the first 4 bytes and the 5th tells if there are more packets to send (8192 bytes or less).
byte[] bytes = ByteBuffer.allocate(4).putInt(8187).array();
auxiliar[0] = bytes[0];
auxiliar[1] = bytes[1];
auxiliar[2] = bytes[2];
auxiliar[3] = bytes[3];
auxiliar[4] = 1;
for(int j = 5; j < 8192; j++){
auxiliar[j] = mybytearray[i*8187+(j-5)];
}
os.write(auxiliar, 0, 8192);
i+=1;
}
if(resto > 0){
byte[] bytes = ByteBuffer.allocate(4).putInt(resto).array();
auxiliar[0] = bytes[0];
auxiliar[1] = bytes[1];
auxiliar[2] = bytes[2];
auxiliar[3] = bytes[3];
auxiliar[4] = 0;
for(int j = 5; j < resto+5; j++){
auxiliar[j] = mybytearray[i*8187+(j-5)];
}
os.write(auxiliar, 0, resto+5);
}
os.flush();
}
을 그리고 클라이언트 측에서 .println() 또는 누가 실행하는 데 시간이 걸리는지간에 readInt()는 무작위로 음수 또는 음수를 반환하기 때문에 클라이언트에서 올바른 방식으로 데이터를받지 못합니다 (메모리 및 기타 예외가 발생하여 힙을 의미 함) .
확실한 것은 동기화에 관한 것이지만 두 가지 방법 간의 스키마 이전은 정확합니다 (클라이언트가 너무 느리고 서버가 너무 빠름).
무슨 일입니까 ?? Thread.sleep을 넣고 싶지 않기 때문에 여기는 좋은 프로그래밍이 아닙니다.
정말 고마워요!
얼마나 많은 다른 스레드가 receiveFileData()를 호출 할 수 있습니까? sendFileData()에 대해서도 같은 질문입니다 ... File -> File transfer를하고 있다면 ... byte [] 이외의 다른 것을 혼란시키는 이유는 무엇입니까? 데이터로드 앞에 하나의 int가 있어야 다른 쪽에서 예상 할 바이트 수를 알 수 있지만 그 외에는 원시 바이트 만 보내면됩니다. – claymore1977
서버에는 새 연결 (accept())을 수신하는 스레드가 하나만 있습니다. 클라이언트가 서버에 연결을 시도하면 서버는 클라이언트와 서버 간의 데이터 흐름을 별도로 관리하는 새 스레드를 생성 한 다음 계속해서 청취합니다. 클라이언트 측에는 하나의 스레드 만 있습니다. 파일의 모든 바이트가 포함 된 전체 버퍼를 보내려고했으나 추락했다고 생각합니다 (지금 집에 없기 때문에 확인해야합니다). 답장을 보내 주셔서 감사합니다. – cabreracanal
그리고이 코드는 변경되지 않은 전체 파일을 한 위치에서 다른 위치로 전송합니다. – claymore1977