客户端类:
/*
* 上传案例的客户端
* 注意在读取完需要上传的源文件以后,调用客户端Socket对象的shutdownOutputStream()
* 此方法可以禁用此套接字的输入流,并且在输入流后面跟上TCP正常连接终止序列
* 这样可以防止上传线程任务代码中读取客户端输出的字节数组时由于读不到-1而使read()方法一直处于线程等待的现象
*/
public class TCPClient {
public static void main(String[] args) throws IOException{
Socket socket = new Socket("127.0.0.1",8000);
OutputStream out = socket.getOutputStream();
FileInputStream fis = new FileInputStream("e:\\demo\\XX.JPG");
byte[] data = new byte[1024];
int len = 0;
while((len = fis.read(data)) != -1) {
out.write(data);
}
socket.shutdownOutput();
InputStream in = socket.getInputStream();
while((len = in.read(data)) != -1) {
System.out.println(new String(data,0,len));
}
fis.close();
socket.close();
}
}
上传线程:
/*
* 上传的线程任务代码类
* 使用构造器传客户端套接字参数的方式,将Socket传入
* 从逻辑上保证了先监听到有客户端套接字的连接请求,再开启线程为此客户端做上传操作
* 而非先开上传线程,再监听客户端套接字
*/
public class Upload implements Runnable{
private Socket socket;
public Upload(Socket socket) {
this.socket = socket;
}
public void run() {
try {
InputStream in = socket.getInputStream();
File upload = new File("e:\\demo1\\upload");
if(!upload.exists()) {
upload.mkdirs();
}
String filename = "java" + System.currentTimeMillis() + new Random().nextInt(99999) + ".jpg";
FileOutputStream out = new FileOutputStream(upload + File.separator + filename);
byte[] data = new byte[1024];
int len = 0;
while((len = in.read(data)) != -1) {
out.write(data,0,len);
}
OutputStream sout = socket.getOutputStream();
sout.write("上传成功".getBytes());
out.close();
socket.close();
}catch(IOException ex) {}
}
}
多线程服务器:
/*
* 多线程是在服务器类里创建,通过一个死循环,保证服务器的8000端口一直打开,循环监听客户端的socket对象
* 当监听到客户端套接字对象时,开启线程执行该客户端的上传操作,此服务器永远都可以为客户端做上传操作
*/
public class TCPThreadServer {
public static void main(String[] args) throws IOException{
ServerSocket server = new ServerSocket(8000);
while(true) {
Socket socket = server.accept();
new Thread(new Upload(socket)).start();
}
}
}