Java TCP文件传输数据随机丢失
[编辑:这篇文章被标记为重复,但没有进行适当的审阅。这两篇文章解决了完全不同的问题,审阅者没有花时间仔细阅读。] 服务器将连接到客户端的三个实例。服务器有三个线程来接收来自这三个客户端的请求。客户端的三个实例中的每一个都有一个ServerThread(服务器从该线程请求文件或文件列表)和一个UserThread(它将接受用户输入并与服务器通信,并根据用户输入接收文件/文件列表) 假设客户机_0需要一个由客户机_1拥有的文件。当client_0的UserThread向服务器请求文件时,服务器与client_1的ServerThread通信,client_1的ServerThread向服务器发送文件的Java TCP文件传输数据随机丢失,java,file,tcp,Java,File,Tcp,[编辑:这篇文章被标记为重复,但没有进行适当的审阅。这两篇文章解决了完全不同的问题,审阅者没有花时间仔细阅读。] 服务器将连接到客户端的三个实例。服务器有三个线程来接收来自这三个客户端的请求。客户端的三个实例中的每一个都有一个ServerThread(服务器从该线程请求文件或文件列表)和一个UserThread(它将接受用户输入并与服务器通信,并根据用户输入接收文件/文件列表) 假设客户机_0需要一个由客户机_1拥有的文件。当client_0的UserThread向服务器请求文件时,服务器与cl
byteArray
。然后服务器将byteArray
发送回客户端0的用户线程,客户端0然后将byteArray
保存为文件
我使用相同类型的代码,服务器从客户端1接收bytearray
,客户端0从服务器接收bytearray
。服务器的代码每次都能完美地工作,并能完美地接收byteArray
,但在客户端0中,接收byteArray
的循环卡在文件的最后一部分,尽管同一类型的循环在服务器中工作得很好。变量position
保存已接收的byteArray
的数量,并且它在客户端0中未达到文件大小,但在服务器中这样做没有任何问题。System.out.println()语句证实了这一点
此外,客户端0中的此问题90%的时间都在发生。在另外10%的情况下,客户端0中的循环与预期的一样工作!为什么会这样
代码很长,但如果有人能够通过并给出一些建议,这将是一个很大的帮助
服务器:
package server;
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
String[] id={"cp 1","cp 2","cp 3"}, pass={"123","456","789"};
ServerSocket welcome = new ServerSocket(6000), tmpSocket;
Socket STsocket, UTsocket;
int startSTport = 6001;
int startUTport = 6011;
// for ServerThread of client
BufferedReader STmsgFrom[] = new BufferedReader[3];
PrintWriter STmsgTo[] = new PrintWriter[3];
DataInputStream[] STfileFrom = new DataInputStream[3];
// for UserThread of client
BufferedReader UTmsgFrom[] = new BufferedReader[3];
PrintWriter UTmsgTo[] = new PrintWriter[3];
DataOutputStream[] UTfileTo = new DataOutputStream[3];
for(int i=0; i<3; i++) {
// connecting initially
System.out.println("Waiting for client "+i);
Socket client = welcome.accept();
PrintWriter send = new PrintWriter(client.getOutputStream(),true);
BufferedReader receive = new BufferedReader(new InputStreamReader(client.getInputStream()));
// sending serial number
send.println(Integer.toString(i));
// sending ports for thread sockets
send.println(Integer.toString(startSTport+i));
send.println(Integer.toString(startUTport+i));
// accepting sockets
tmpSocket = new ServerSocket(startSTport+i);
STsocket = tmpSocket.accept();
tmpSocket = new ServerSocket(startUTport+i);
UTsocket = tmpSocket.accept();
// creating communications
STmsgFrom[i] = new BufferedReader(new InputStreamReader(STsocket.getInputStream()));
STmsgTo[i] = new PrintWriter(STsocket.getOutputStream(),true);
STfileFrom[i] = new DataInputStream(STsocket.getInputStream());
UTmsgFrom[i] = new BufferedReader(new InputStreamReader(UTsocket.getInputStream()));
UTmsgTo[i] = new PrintWriter(UTsocket.getOutputStream(),true);
UTfileTo[i] = new DataOutputStream(UTsocket.getOutputStream());
System.out.println("Connected client "+i);
}
ClientThread ct0 = new ClientThread(0,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
ClientThread ct1 = new ClientThread(1,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
ClientThread ct2 = new ClientThread(2,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
ct0.start();
ct1.start();
ct2.start();
System.out.println("Server Stup Complete!");
}
}
class ClientThread extends Thread {
String msg;
int cid;
BufferedReader[] STmsgFrom;
PrintWriter[] STmsgTo;
DataInputStream[] STfileFrom;
BufferedReader[] UTmsgFrom;
PrintWriter[] UTmsgTo;
DataOutputStream[] UTfileTo;
public ClientThread(int cid,BufferedReader[] STmsgFrom,PrintWriter[] STmsgTo,DataInputStream[] STfileFrom,BufferedReader[] UTmsgFrom,PrintWriter[] UTmsgTo,DataOutputStream[] UTfileTo) {
this.cid=cid;
this.STmsgFrom=STmsgFrom;
this.STmsgTo=STmsgTo;
this.STfileFrom = STfileFrom;
this.UTmsgFrom=UTmsgFrom;
this.UTmsgTo=UTmsgTo;
this.UTfileTo = UTfileTo;
}
@Override
public void run() {
while(true) {
try {
// receiving request from receiver UserThread
msg = UTmsgFrom[cid].readLine();
if(msg.equals("get list")) { // receiver requested for file list
System.out.println("Request from "+cid+": "+msg);
for(int i=0; i<3; i++) {
if(i==cid) continue;
// sending request to sender ServerThread
STmsgTo[i].println("give list");
System.out.println("Request to "+i);
// receive file count from sender ServerThread
int cnt = Integer.parseInt(STmsgFrom[i].readLine());
System.out.println(i+" has files: "+cnt);
// sending source identity to receiver UserThread
UTmsgTo[cid].println(Integer.toString(i));
// send file count back to receiver UserThread
UTmsgTo[cid].println(Integer.toString(cnt));
// get and send file names to receiver
for(int j=0; j<cnt; j++) {
msg = STmsgFrom[i].readLine();
UTmsgTo[cid].println(msg);
}
}
} else if(msg.equals("get file")) {
// get source id and filename
int source = Integer.parseInt(UTmsgFrom[cid].readLine());
String fileName = UTmsgFrom[cid].readLine();
//System.out.println("get source id and filename");
// ask source about file
STmsgTo[source].println("give file");
STmsgTo[source].println(fileName);
boolean fileOk = Boolean.parseBoolean(STmsgFrom[source].readLine());
//System.out.println("ask source about file");
// telling receiver about file status
UTmsgTo[cid].println(Boolean.toString(fileOk));
//System.out.println("telling receiver about file");
if(fileOk) {
// get copy request from receiver
msg = UTmsgFrom[cid].readLine();
//System.out.println("receiver copy command");
if(msg.equals("yes copy")) {
System.out.println("Copying \'"+fileName+"\' from "+source+" to "+cid);
// tell sender to copy
STmsgTo[source].println("yes copy");
//System.out.println("tell sender copy command");
// copy from SENDER
// get file size
int FILE_SIZE = Integer.parseInt(STmsgFrom[source].readLine());
byte[] fileBytes = new byte[FILE_SIZE];
System.out.println("Get file size "+FILE_SIZE);
// get file data
int portion = STfileFrom[source].read(fileBytes,0,fileBytes.length);
int position = portion;
do {
portion = STfileFrom[source].read(fileBytes,position,fileBytes.length-position);
if(portion>=0) {
position += portion;
}
System.out.println("position = "+position);
} while(position<FILE_SIZE);
System.out.println("Get file data "+position);
// copy to RECEIVER
// send file size
UTmsgTo[cid].println(Integer.toString(FILE_SIZE));
//System.out.println("send file size");
// send file data
UTfileTo[cid].write(fileBytes,0,position);
UTfileTo[cid].flush();
//System.out.println("send file data");
System.out.println("Copying \'"+fileName+"\' complete");
} else {
// tell sender to ignore copy process
STmsgTo[source].println("no copy");
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
包服务器;
导入java.io.*;
导入java.net。*;
公共类服务器{
公共静态void main(字符串[]args)引发异常{
字符串[]id={“CP1”、“CP2”、“CP3”},pass={“123”、“456”、“789”};
ServerSocket welcome=新的ServerSocket(6000),tmpSocket;
插座STsocket,UTsocket;
int startSTport=6001;
int startUTport=6011;
//用于客户端的服务器线程
BufferedReader STmsgFrom[]=新的BufferedReader[3];
PrintWriter STmsgTo[]=新的PrintWriter[3];
DataInputStream[]STfileFrom=新DataInputStream[3];
//用于客户端的用户线程
BufferedReader UTmsgFrom[]=新BufferedReader[3];
PrintWriter UTmsgTo[]=新的PrintWriter[3];
DataOutputStream[]UTfileTo=新DataOutputStream[3];
对于(int i=0;iServerSocket.accept()是阻塞的,您不能从同一线程调用它两次
每个ServerSocket都必须在自己的线程中运行。@EJP-这个问题是如何重复的?您是否在这里花时间阅读了这个问题?
package client;
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
String msg;
InetAddress inetAddress = InetAddress.getLocalHost();
String[] allPaths= {"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_1_folder",
"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_2_folder",
"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_3_folder"};
// connecting to welcome socket
Socket server = new Socket(inetAddress,6000);
BufferedReader receive = new BufferedReader(new InputStreamReader(server.getInputStream()));
BufferedReader receiveUser = new BufferedReader(new InputStreamReader(System.in));
PrintWriter send = new PrintWriter(server.getOutputStream(),true);
// receiving serial number
int cid = Integer.parseInt(receive.readLine());
// receiving port numbers for thread sockets
int STport = Integer.parseInt(receive.readLine());
int UTport = Integer.parseInt(receive.readLine());
// connecting sockets
Socket STsocket = new Socket(inetAddress,STport);
Socket UTsocket = new Socket(inetAddress,UTport);
System.out.println("Connected to the server.\nSerial: "+cid+"\nFolder path: "+allPaths[cid]);
ServerThread st = new ServerThread(allPaths[cid],STsocket);
UserThread ut = new UserThread(cid,allPaths[cid],UTsocket);
st.start();
ut.start();
}
}
class UserThread extends Thread {
int cid;
String msg,folderPath;
BufferedReader msgFromServer,fromUser;
PrintWriter msgToServer;
// for file
DataInputStream fileFromServer;
BufferedOutputStream writeFile;
public UserThread(int cid,String folderPath,Socket socket) {
try {
this.cid = cid;
this.folderPath = folderPath;
fromUser = new BufferedReader(new InputStreamReader(System.in));
msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
msgToServer = new PrintWriter(socket.getOutputStream(),true);
// for file
fileFromServer = new DataInputStream(socket.getInputStream());
} catch(Exception ex) {
ex.printStackTrace();
}
}
@Override
public void run() {
//System.out.println("User Thread Started!");
while(true) {
try {
msg = fromUser.readLine();
if(msg.equals("get list")) {
// sending request to server
msgToServer.println("get list");
// getting file list from server
System.out.println("-------------------------------------------");
for(int i=0; i<2; i++) {
// getting source id
int source = Integer.parseInt(msgFromServer.readLine());
System.out.println("Source: "+source);
int cnt = Integer.parseInt(msgFromServer.readLine());
System.out.println("Files: "+cnt);
System.out.println("--------------");
for(int j=0; j<cnt; j++) {
msg = msgFromServer.readLine();
System.out.println(msg);
}
System.out.println("-------------------------------------------");
}
} else if(msg.equals("get file")) {
// GETTING A FILE
int source;
while(true) {
System.out.println("File Source: ");
try {
source = Integer.parseInt(fromUser.readLine());
if(0<=source && source<=2 && source!=cid) {
break;
} else {
System.out.println("Error: File source invalid. Try again.");
}
} catch(Exception ex) {
System.out.println("Error: File source invalid. Try again.");
}
}
System.out.println("File Name: ");
String fileName = fromUser.readLine();
// send request to server to check file
msgToServer.println("get file");
msgToServer.println(Integer.toString(source));
msgToServer.println(fileName);
// receiving file status
boolean fileOk = Boolean.parseBoolean(msgFromServer.readLine());
if(!fileOk) {
System.out.println("Error: File does not exist at source.");
} else {
System.out.println("File is available!!");
System.out.println("Want to copy \'"+fileName+"\'? (y/n)");
msg = fromUser.readLine();
if(msg.equals("y")||msg.equals("Y")) {
// tell server to copy file
msgToServer.println("yes copy");
// COPY PROCESS
// get file size
int FILE_SIZE = Integer.parseInt(msgFromServer.readLine());
System.out.println("File size: "+FILE_SIZE+" bytes.");
byte[] fileBytes = new byte[FILE_SIZE];
// get file data
int portion = fileFromServer.read(fileBytes,0,fileBytes.length);
int position = portion;
do {
portion = fileFromServer.read(fileBytes,position,fileBytes.length-position);
if(portion>=0) {
position += portion;
}
System.out.println("position = "+position);
} while(position<FILE_SIZE);
System.out.println("Total "+position+" bytes received.");
// write file data
File file = new File(folderPath + "\\" + fileName);
writeFile = new BufferedOutputStream(new FileOutputStream(file));
writeFile.write(fileBytes,0,position);
writeFile.flush();
writeFile.close();
System.out.println("Copying complete.");
} else {
msgToServer.println("no copy");
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
class ServerThread extends Thread {
String msg,folderPath;
BufferedReader msgFromServer;
PrintWriter msgToServer;
// for file
DataOutputStream fileToServer;
BufferedInputStream readFile;
public ServerThread(String folderPath,Socket socket) {
try {
this.folderPath = folderPath;
msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
msgToServer = new PrintWriter(socket.getOutputStream(),true);
// for file
fileToServer = new DataOutputStream(socket.getOutputStream());
} catch(Exception ex) {
ex.printStackTrace();
}
}
@Override
public void run() {
//System.out.println("Server Thread Started!");
while(true) {
try {
msg = msgFromServer.readLine();
if(msg.equals("give list")) {
//System.out.println("Request from server: "+msg);
File folder = new File(folderPath);
File[] fileList = folder.listFiles();
int cnt = fileList.length;
//System.out.println("Files: "+cnt);
// give file count back to server
msgToServer.println(Integer.toString(cnt));
// give file list back to server
for(int i=0; i<cnt; i++) {
msgToServer.println(fileList[i].getName());
}
} else if(msg.equals("give file")) {
// receive file name
String fileName = msgFromServer.readLine();
// telling server about file status
File file = new File(folderPath + "\\" + fileName);
boolean fileOk = file.exists();
msgToServer.println(Boolean.toString(fileOk));
if(fileOk) {
// getting copy request
msg = msgFromServer.readLine();
if(msg.equals("yes copy")) {
// COPY PROCESS
// send file size
int FILE_SIZE = (int)file.length();
msgToServer.println(Integer.toString(FILE_SIZE));
// read file data
readFile = new BufferedInputStream(new FileInputStream(file));
byte[] fileBytes = new byte[FILE_SIZE];
readFile.read(fileBytes,0,fileBytes.length);
readFile.close();
// send file data
fileToServer.write(fileBytes,0,fileBytes.length);
fileToServer.flush();
} // otherwise end of conversation
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}