我的程序是典型的服务器 - 客户端应用程序。问题是,当我尝试发送文件时,由于某种原因,客户端套接字比服务器套接字发送更多的字节。更奇怪的是,这些字节位于开头,它们的数量根据文件大小而变化。当我尝试发送1x1px文件时,有6个字节的偏移量(6个字节的添加数据,如果我跳过它们,给出了正确的图像),而800x600字节有较大的一个(完全第二个输出文件大于第二个输入56个字节) 。在互联网上搜索后,我发现只有两个建议是事先尝试清除缓冲区,我想我尝试了但它只是“吃”了我的第一个inStream.read()。 第二个与pacage的发送方式有关,大小必须乘以一些数字?但它似乎很奇怪,因为它们不会在文件的末尾添加一些空格,而不是在开头?
客户端类
public class Client{
import java.io.BufferedReader;
public class Client implements Runnable {
static Socket clientSocket = null;
static Socket iClientSocket = null;
static PrintWriter out = null;
static BufferedReader in = null;
static InputStream iin = null;
public static void main(String[] args) {
int port = Integer.valueOf(args[1]);
String host = args[0];
try {
clientSocket = new Socket(host, port);
iClientSocket = new Socket(host, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
iin = iClientSocket.getInputStream();
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + host);
System.exit(-1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: "
+ host);
System.exit(-1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(
System.in));
String userInput;
try {
new Thread(new Client()).start();
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
}
System.out.println("Closing sockets, closing streams");
out.close();
in.close();
stdIn.close();
iClientSocket.close();
clientSocket.close();
} catch (IOException e) {
System.exit(-1);
}
}
@Override
public void run() {
String a = null;
try {
while (true) {
if((a = in.readLine()) == null)
continue;
//System.out.println("Tried to read");
int n;
try{
n = Integer.valueOf(a);
}catch(NumberFormatException e){
System.out.println(a);
n=1;
//continue;
}
a = "";
for (int i = 0; i < n; i++)
a += in.readLine() + "\n";
System.out.println(a);
// if(a.contains("POST"),)
if (a.compareToIgnoreCase("EXIT") == 0) {
System.out.println("Exiting");
break;
}
if (a.endsWith("Sending File\n")) {
System.out.println("Recieving image.");
a=in.readLine();
a=in.readLine();
FileOutputStream iout = new FileOutputStream(a);
int fileSize=Integer.parseInt(in.readLine());
int total=0;
int step = 1500;
int bufferSize = 0;
// if(step>fileSize)
// bufferSize=(int) fileSize;
// else
bufferSize = step;
byte[] buffer = new byte[bufferSize];
int read=0;
while (fileSize-total>0 && (read = iin.read(buffer, 0, (int)Math.min(buffer.length, fileSize-total))) > 0) {
iout.write(buffer, 0, read);
//out.println("saved packet");
total+=read;
}
iout.flush();
iout.close();
System.out.println("Image recieved");
}
}
} catch (IOException e) {
System.exit(-1);
}
}
}
服务器类,负责发送
public class Server implements Runnable {
static ServerSocket serverSocket;
Socket tempSocket;
Socket tempSocket2;
static volatile List<User> usersList = new ArrayList<User>();
static boolean waitForNew = true;
PrintWriter tempOut;
volatile User[] tempUser;
volatile boolean isReadingN = false;
public Server(Socket _s, Socket _s2) {
tempSocket = _s;
tempSocket2 = _s2;
}
public Server(PrintWriter nOut, User[] user) {
tempOut = nOut;
tempUser = user;
isReadingN = true;
}
@Override
public void run() {
if (isReadingN) {
while (true) {
if (tempUser != null && tempUser.length > 0
&& tempUser[0] != null)
break;
}
User[] myUser = new User[1];
myUser[0] = tempUser[0];
// myUser[0]=usersList.
while (true) {
if (myUser[0].isCurrentlyLoggedIn() == false)
break;
String[] toSend = null;
if (myUser[0].isNotificable())
toSend = myUser[0].printNotifications().split("\n");
else
continue;
//tempOut.println("");
tempOut.println("1");
tempOut.println(myUser[0].getName());
int sendL=toSend.length;
tempOut.println(String.valueOf(sendL));
for (int i = 0; i < toSend.length; i++)
tempOut.println(toSend[i]);
}
return;
}
Socket clientSocket = tempSocket;
System.out.println("Initiating conversation with the client");
String inputLine;
try {
System.out.print("creating server out...");
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
Socket iClientSocket = tempSocket2;
ObjectOutputStream iout = new ObjectOutputStream(
iClientSocket.getOutputStream());
System.out.println("OK!");
System.out.print("creating server in...");
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
System.out.println("OK!");
System.out.print("creating server image streams...");
System.out.println("OK!");
System.out.println("Server initiating conversation");
User[] currentUser = new User[1];
new Thread(new Server(out, currentUser)).start();
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
boolean[] downloadPicture = new boolean[1];
downloadPicture[0] = false;
String input = Command.call(inputLine, currentUser, usersList,
downloadPicture);
String[] toSend;
if (input != null) {
toSend = input.split("\n");
} else
toSend = new String[0];
out.println(String.valueOf(toSend.length));
for (int i = 0; i < toSend.length; i++)
out.println(toSend[i]);
if (downloadPicture[0]) {
out.println("1");
out.println("Sending File");
System.out.println("Sending File");
String[] temp = inputLine.split(" ");
String path = temp[temp.length - 1];
path = path.replace("\\", "\\\\");
File f = new File(path);
temp=path.split("\\\\");
String fileName=temp[temp.length-1];
out.println("1");
out.println(fileName);
if (f.exists()) {
FileInputStream iin = new FileInputStream(path);
long fileSize = f.length();
out.println(fileSize);
int step = 1500;
int bufferSize = 0;
if (step > fileSize)
bufferSize = (int) fileSize;
else
bufferSize = step;
int bytesRead = 0;
byte[] buffer = new byte[bufferSize];
iout.flush();
while ((bytesRead = iin.read(buffer)) > 0) {
//iout.flush();
iout.write(buffer, 0, bytesRead);
// System.out.println(in.readLine());
}
// iout.write(buffer,0,0);
iout.flush();
System.out.println("File sent.");
iin.close();
} else{
out.println("1");
out.println("Error: File does not exit.");}
} else
//out.println(" ");
if (inputLine.equals("EXIT")) {
waitForNew = false;
break;
}
}
// End communication graciously
System.out.println("Closing sockets, closing streams");
out.close();
in.close();
clientSocket.close();
serverSocket.close();
} catch (IIOException e) {
System.out.println("Error: Could not find file");
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
System.out.println("Error");
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
// Create socket on port given in argument, localhost
if (args.length == 0) {
System.out
.println("Not enough arguments. Try Server <port number>");
System.exit(-1);
}
int port = 0;
try {
port = Integer.valueOf(args[0]);
System.out.println("Application start");
serverSocket = new ServerSocket(port);
System.out.println("Created socket on port " + port);
} catch (NumberFormatException c) {
System.out
.println("Incorrect port number. Try Server <port number>");
System.exit(-1);
} catch (IOException e) {
System.exit(-1);
}
// Waiting for client
System.out.println("Waiting for client...");
Socket clientSocket = null;
Socket iClientSocket = null;
while (waitForNew) {
try {
clientSocket = serverSocket.accept();
iClientSocket = serverSocket.accept();
new Thread(new Server(clientSocket, iClientSocket)).start();
} catch (IOException e) {
System.out.println("Accept failed: " + port);
System.exit(-1);
}
}
}
}
命令类,在服务器端操作命令,返回输出。
public class Command {
static volatile List<Status> statusList = new ArrayList<Status>();
static Object block_statusList = new Object();
public static String call(String arg, User[] user, List<User> userlist,
boolean[] downloadPicture) {
String command[] = arg.split(" ");
if (command.length == 0)
return "";
else if (command[0].compareTo("LOGIN") == 0)
return login(command, user, userlist);
else if (command[0].compareTo("EXIT") == 0)
return exit(command, user, userlist);
else if (user == null || user.length != 1 || user[0] == null
|| !user[0].isCurrentlyLoggedIn())
return "You need to login first. Try LOGIN <username>";
else if (command[0].compareTo("LOGOUT") == 0)
return logout(command, user, userlist);
else if (command[0].compareTo("POST") == 0)
return post(command, user, userlist, downloadPicture);
else if (command[0].compareTo("TIMELINE") == 0)
return timeline(command, user, userlist);
else if (command[0].compareTo("FOLLOW") == 0)
return follow(command, user, userlist);
else if (command[0].compareTo("UNFOLLOW") == 0)
return unfollow(command, user, userlist);
else if (command[0].compareTo("VIEWSTATUS") == 0)
return viewstatus(command, user, userlist);
else if (command[0].compareTo("LISTUSER") == 0)
return listuser(command, user, userlist);
else if (command[0].compareTo("VIEWUSER") == 0)
return viewuser(command, user, userlist);
else if (command[0].compareTo("COMMENT") == 0)
return comment(command, user, userlist);
else
return "Command not recognized";
}
private static String logout(String[] arg, User[] user, List<User> userlist) {
if (arg.length != 1)
return "Wrong number of parameters. LOGOUT does not take any parameters";
user[0].setCurrentlyLoggedIn(false);
return "Logged out.";
}
private static String[] parseArg(String[] arg) {
int startCommas = 0;
int endCommas = 0;
for (int i = 0; i < arg.length; i++) {
if (startCommas == 0 && arg[i].startsWith("\""))
startCommas = i;
if (startCommas != 0 && arg[i].endsWith("\""))
endCommas = i;
}
if (startCommas != endCommas) {
String[] newArg = new String[arg.length + startCommas - endCommas];
for (int i = 0; i < startCommas; i++)
newArg[i] = arg[i];
newArg[startCommas] = "";
for (int i = startCommas; i < endCommas; i++)
newArg[startCommas] += arg[i] + " ";
newArg[startCommas] += arg[endCommas];
for (int i = endCommas + 1; i < arg.length; i++)
newArg[i - endCommas] = arg[i];
return newArg;
}
return arg;
}
private static String comment(String[] arg, User[] user, List<User> userlist) {
synchronized (block_statusList) {
arg = parseArg(arg);
int SID;
if (arg.length != 3)
return "Wrong number of parameters. Try COMMENT <Status ID> \"Comment text\"";
if (arg[2].charAt(0) != '"'
|| arg[2].charAt(arg[1].length() - 1) != '"')
return "Text of message has to be in quotation marks. Try POST \"post text\"";
String temp = arg[2].substring(1, arg[2].length() - 1);
try {
SID = Integer.valueOf(arg[1]);
} catch (NumberFormatException e) {
return "Status ID has to be a number. Try COMMENT <Status ID> \"Comment text\"";
}
Comment c = new Comment(temp, user);
statusList.get(SID).addComment(c);
return "Comment succeeded";
}
}
private static String viewuser(String[] arg, User[] user,
List<User> userlist) {
synchronized (block_statusList) {
if (arg.length != 2)
return "Wrong number of parameters. Try VIEWUSER <user>";
String r = "";
for (User u : userlist)
if (u.getName().compareTo(arg[1]) == 0)
r = u.printUser();
return r;
}
}
private static String listuser(String[] arg, User[] user,
List<User> userlist) {
if (arg.length != 1)
return "Wrong number of parameters. LISTUSER doesn't take any parameters";
String r = "";
for (User u : userlist)
r += u.getName() + "\n";
return r;
}
private static String viewstatus(String[] arg, User[] user,
List<User> userlist) {
synchronized (block_statusList) {
int SID;
if (arg.length != 2)
return "Wrong number of parameters. Try VIEWSTATUS <Status ID>";
try {
SID = Integer.valueOf(arg[1]);
} catch (NumberFormatException e) {
return "Status ID has to be a number. Try VIEWSTATUS <Status ID>";
}
if (SID >= statusList.size())
return "Status ID too big.";
return statusList.get(SID).printWithComments();
}
}
private static String unfollow(String[] arg, User[] user,
List<User> userlist) {
if (arg.length != 2)
return "Wrong number of parameters. Try UNFOLLOW <username>";
boolean removed = false;
for (User u : userlist) {
if (u.getName().compareTo(arg[1]) == 0) {
user[0].removeFriend(arg[1]);
u.removeFollower(user[0].getName());
removed = true;
}
}
if (!removed)
return "User not found.";
return "Follow succeded. " + user[0].printFriends();
}
private static String follow(String[] arg, User[] user, List<User> userlist) {
if (arg.length != 2)
return "Wrong number of parameters. Try FOLLOW <username>";
if(user[0]!=null && user.length!=0 && user[0]!=null && user[0].getName().compareTo(arg[1])==0)
return "You cannot follow yourself. Try FOLLOW <username>";
User[] followed = null;
for (User u : userlist) {
if (u.getName().compareTo(arg[1]) == 0) {
followed = new User[1];
followed[0] = u;
user[0].addFriend(followed);
followed[0].addFollower(user);
}
}
if (followed == null)
return "User not found.";
return "Follow succeded. Current " + user[0].printFriends();
}
public static String login(String[] arg, User[] user, List<User> userslist) {
if (arg.length != 2)
return "Wrong number of parameters. Try LOGIN <username>";
if (user.length > 0 && user[0] != null) {
if (user[0].isCurrentlyLoggedIn())
return "User already logged in. Try logging out first";
}
for (User l : userslist) {
if (l.getName().compareTo(arg[1]) == 0) {
if (l.isCurrentlyLoggedIn())
return "That user is already logged in.";
user[0] = l;
user[0].setCurrentlyLoggedIn(true);
return "Login succeeded";
}
}
User newUser = new User(arg[1]);
userslist.add(newUser);
user[0] = newUser;
user[0].setCurrentlyLoggedIn(true);
return "Login succeeded. Created new user.";
}
public static String post(String[] arg, User[] user, List<User> userslist,
boolean[] downloadPicture) {
arg = parseArg(arg);
if (arg.length != 2 && arg.length != 3)
return "Wrong number of parameters. Try POST \"post text\"";
if (arg[1].charAt(0) != '"'
|| arg[1].charAt(arg[1].length() - 1) != '"')
return "Text of message has to be in quotation marks. Try POST \"post text\"";
String temp = arg[1].substring(1, arg[1].length() - 1);
Status s;
try {
s = new Status(temp, statusList.size(), user);
} catch (Exception e) {
System.out.println("Error: Could not create Status");
e.printStackTrace();
return "Error";
}
if(arg.length==3)
s.hasImage(arg[2]);
user[0].addStatus(s);
statusList.add(s);
if (arg.length == 3)
downloadPicture[0] = true;
return "Successfully added status";
}
public static String timeline(String[] arg, User[] user,
List<User> userslist) {
if (arg.length != 1)
return "Wrong number of parameters. TIMELINE doesn't take any parameters";
List<Status> Timeline = new ArrayList<Status>();
Timeline.addAll(user[0].getStats());
for (User l : user[0].getFriends())
Timeline.addAll(l.getStats());
Collections.sort(Timeline);
String result = "";
for (Status s : Timeline)
result += s.print() + "\n" + "Comments[" + s.getComments().size()
+ "]\n\n";
return result;
}
public static String exit(String[] arg, User[] user, List<User> userslist) {
if (arg.length != 1)
return "Wrong number of parameters. EXIT doesn't take any parameters";
if (user[0] != null)
user[0].setCurrentlyLoggedIn(false);
return "EXIT";
}
}
添加通知
答案 0 :(得分:1)
您没有发送额外的字节,并且您没有收到额外的字节,但您肯定会在接收端向该文件写入额外的字节。
您的发送代码是正确的,您的接收代码不是。看看write()
电话之间的区别。一个使用接收计数:一个不使用。前者是对的。在Java中复制流的方法如下:
int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
out.close();
in.close();
两端。但是在这种情况下,当您为了进一步的命令保持套接字打开时,您需要在图像之前发送图像大小,并且需要一种发送和接收不会干扰图像的命令的方法,{{1}无法完成。因此,您需要使用BufferedReader
和DataOutputStream
,如下所示:
DataInputStream
Modulo bug。