[编辑:此帖子已标记为重复,未经正确审核。这两个帖子解决了完全不同的问题,审稿人没有花时间仔细阅读。]
服务器将连接到三个客户端实例。服务器有三个线程来接收来自这三个客户端的请求。客户端的三个实例中的每一个都将具有ServerThread(服务器从该线程请求文件或文件列表)和UserThread(它将接受用户输入并与服务器通信并根据用户输入接收文件/文件列表)
让我们说client_0想要一个拥有client_1的文件。当client_0的UserThread向服务器请求文件时,服务器与client_1的ServerThread通信,client_1的ServerThread将文件的byteArray
发送到服务器。然后,服务器将byteArray
发送回client_0和client_0的UserThread,然后将byteArray
保存为文件。
我使用相同类型的代码让服务器从client_1接收bytearray
,并使用client_0从服务器接收byteArray
。服务器的代码每次都完美地工作并且完美地接收byteArray
但是在client_0中,接收byteArray
的循环卡在文件的最后部分,尽管相同类型的循环正在工作完美的服务器。变量position
包含已收到的byteArray
的多少,并且它没有到达client_0中的FILE_SIZE
,但在服务器中没有任何问题。 System.out.println()
语句证实了这一点。
此外,client_0中的这个问题发生在90%的时间。在另外10%中,client_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();
}
}
}
}
客户端:
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();
}
}
}
}
我知道我做了一些不必要的事情,比如给所有不同的套接字提供不同的端口。如果它们不是我问题的原因,请忽略它们。
答案 0 :(得分:0)
ServerSocket.accept()是阻塞的,你不能从同一个线程中调用它两次。
每个ServerSocket都必须在自己的线程中运行。