import java.io.*;
import java.net.*;public class FileServer implements Runnable
{
private ServerSocket server;
public FileServer(int port)
{
try
{
server = new ServerSocket(port);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void run()
{
try
{
Socket socket = server.accept();
File file = new File("d:\\2.bmp");
FileOutputStream fileOut = new FileOutputStream(file);
InputStream socketIn = socket.getInputStream();
OutputStream socketOut = socket.getOutputStream();
DataInputStream dataIn = new DataInputStream(socketIn);
PrintWriter writerOut = new PrintWriter(new OutputStreamWriter(socketOut));
byte[] bytes = new byte[1024];
while ((dataIn.read(bytes)) != -1)
{
fileOut.write(bytes);
}
fileOut.close();
//writerOut.println("OK");
//writerOut.flush();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new Thread(new FileServer(9999)).start();
}
}import java.io.*;
import java.net.*;public class FileClient implements Runnable
{
private Socket socket;
public FileClient(String ip, int port)
{
try
{
socket = new Socket(ip, port);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void run()
{
try
{
InputStream socketIn = socket.getInputStream();
File file = new File("d:\\1.bmp");
FileInputStream fileIn = new FileInputStream(file);
OutputStream socketOut = socket.getOutputStream();
BufferedReader readerIn = new BufferedReader(new InputStreamReader(socketIn));
DataOutputStream dataOut = new DataOutputStream(socketOut); byte[] bytes = new byte[1024];
while ((fileIn.read(bytes)) != -1)
{
dataOut.write(bytes);
}
dataOut.close();
//String str = readerIn.readLine();
//System.out.println(str);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new Thread(new FileClient("localhost", 9999)).start();
}
}
这段代码这样写是没有问题的,可以实现文件传输功能,但是为什么加上被注释掉的语句后就出现错误了呢?错误的大致原因是这样的,Client在执行String str = readerIn.readLine();这句话地时候,并没有像以往一样变成阻塞态,而是直接抛出了一个错误。我不是很明白为什么会抛出一个错误,请高手帮忙解释一下,顺便也帮忙修改一下,谢谢了。
2:flush好像会是post方式发送。
我通常的做法是
客户端关闭前给服务器端发送一个close指令,然后客户端线程睡眠1000ms等待服务器端流,socket 关闭。
服务端收到close指令后进行流关闭,socket关闭的操作,最后客户端睡醒后,同样进行流关闭,socket关闭的操作。
你可以在客户端加上对readerIn.available()的判断。比如
long start = System.currentTimeMillis();
while (readIn.available() <= 0) { // 其实更好是判断 < "OK".length(),因为可能有一个物理包,正好到O为止,K要在下一个buffer里面才能收到,而恰巧此时,客户端代码被执行。
Thread.sleep(500);
if (System.currentTimeMillis() - start >= 10000) {
throw new RuntimeException("Timeout");
}
}
readIn.readLine();
import java.net.*;public class FileServer implements Runnable
{
private ServerSocket server; public FileServer(int port)
{
try
{
server = new ServerSocket(port);
}
catch (IOException e)
{
e.printStackTrace();
}
} public void run()
{
try
{
Socket socket = server.accept();
File file = new File("2.jpg");
FileOutputStream fileOut = new FileOutputStream(file);
InputStream socketIn = socket.getInputStream();
OutputStream socketOut = socket.getOutputStream();
DataInputStream dataIn = new DataInputStream(socketIn);
PrintWriter writerOut = new PrintWriter(new OutputStreamWriter(socketOut));
byte[] bytes = new byte[1024];
boolean flag=true;
try{
//你这里,read返回-1的时候就停止接收,其实你这样做,是很不科学的
//因为,read什么时候会返回-1,如果是读取文件,读到文件尾标记会返回-1
//而对于从TCP获得的输入流而言,当对方的输出流关闭后,你这输入流的read
//才会返回-1。那么这样做的坏处有几点
//1:就如你这里的程序一样,对方的输出流关闭的话,引发Socket连接关闭,你就
//不能再传递信息了。所以对方不能关闭,可是对方不关闭,你就不会返回-1。
//那你的程序就无限等待了
//2:你这里只传输一个文件,如果是一批呢,难道你不停关闭再不停打开?
//所以,正宗的做法应该是在传递的数据中加上一些标记信息,通过这些标记
//信息来判断什么时候传输结束,什么时候传输开始,等等
while ((dataIn.read(bytes)) != -1)
{
//不过呢,我这里没有加标记信息,而对方读完后也没关闭流。我干的
//是设置了socket的接收超时时间为100ms。当然,其实这样很不科学滴。
//不过演示给你看是没问题的。
//我是在dataIn第一次读完才设置的。这是防止你先启动FileServer再启动
//FileClient的时候不够快,这里已经超时了。
//设置超时以后。对方传完了,并不关闭流。而你还在read,超时100ms后
//会抛出异常,不过我在接收异常的代码中什么也没有做
//因为下面就是按你的意思去发送那个信息
if(flag){
socket.setSoTimeout(100);
flag=false;
}
fileOut.write(bytes);
}
}catch(Exception e){
if(e instanceof SocketException){
}
}
fileOut.close(); writerOut.println("OK");
writerOut.flush();
//对了,最后再说一下,你用流式传输文件,是相当不好滴。因为流式传输,速度相当的慢的。
//应该用数据报传输
}
catch (IOException e)
{
e.printStackTrace();
}
} public static void main(String[] args)
{
new Thread(new FileServer(9999)).start();
}
}import java.io.*;
import java.net.*;public class FileClient implements Runnable
{
private Socket socket; public FileClient(String ip, int port)
{
try
{
socket = new Socket(ip, port);
}
catch (IOException e)
{
e.printStackTrace();
}
} public void run()
{
try
{
InputStream socketIn = socket.getInputStream();
File file = new File("screen.jpg");
FileInputStream fileIn = new FileInputStream(file);
OutputStream socketOut = socket.getOutputStream();
BufferedReader readerIn = new BufferedReader(new InputStreamReader(socketIn));
DataOutputStream dataOut = new DataOutputStream(socketOut); byte[] bytes = new byte[1024];
while ((fileIn.read(bytes)) != -1)
{
dataOut.write(bytes);
}
//dataOut.close();
String str = readerIn.readLine();
System.out.println(str);
}
catch (Exception e)
{
e.printStackTrace();
}
} public static void main(String[] args)
{
new Thread(new FileClient("localhost", 9999)).start();
}
}
Client是在发送数据,而Server实在接受数据。
socket = new Socket(ip, port); //client端
Socket socket = server.accept(); //server端。而楼主你在Client端
InputStream socketIn = socket.getInputStream(); 你认为你能得到什么数据?这里是源头,根本就没数据吗。
然后又 BufferedReader readerIn = new BufferedReader(new InputStreamReader(socketIn));
本身这里面这有TCP的确认信息,没有任何数据,所以你read的时候就是-1;
而Server端
OutputStream socketOut = socket.getOutputStream(); //你还要想发送回去数据么?out是往外发送的。
PrintWriter writerOut = new PrintWriter(new OutputStreamWriter(socketOut));
writerOut.println("OK");
writerOut.flush();这样就会发送空数据出去了,因为out中没有内容所以一直是-1以上只是我的意见。不知道这么久了记的正确不。