/*
* 前两个视频客户端上传图片给服务端的若干问题:
*
* 1.服务端开启,此时张三连进来,获取张三Socket对象,张三上传完毕,关闭张三Socket,ss.close(),服务端也关闭,所以
* 此时其余人无法上传文件。
*
* 2.为克服问题1,有如下程序:
* ServerSocket ss = new ServerSocket(20000);
* while(true){
* Socket s = ss.accept();
* 流对象的不断读写操作......
* s.close();
* }
* 此时问题1解决,但是新问题出现,由于此时只有主线程这一个线程在工作,所以客户端1进入while循环,获取客户端1的Socket对象,
* 开始读写操作,此时客户端2连进来了,那么获取不到客户端2的Socket对象,因为主线程在操作客户端1的读写,所以还是有问题。
* →上传图片需要排队。(如别人登录新浪,你登录不了,同一时间只一个登录新浪)
*/
/**
* 上述问题可用多线程并发解决,思考发现while循环中的“流对象的不断读写操作......”不管哪个客户端连进来都要做这步,
* 而Socket s = ss.accept()可以用一个线程单独封装操作,即客户端1用线程1,客户端2用线程2……
*
* 程序运行,客户端1连进来,主线程立马安排线程1给客户端1(下面由线程1带领客户端1完成读写等操作),此时主线程立马回到
* 开始等待客户端2连接,客户端2一连接,主线程立马安排线程2给客户端2(下面由线程2带领客户端2完成读写操作),此时主线程
* 立马回到开始等待客户端3连接……如此往复,这就是【服务器原理:客户端并发访问】,程序如下:
* ServerSocket ss = new ServerSocket(20000);
* while(true){
* Socket s = ss.accept();主线程在这等着,有一个客户端连接
* new Thread(new Task(s)).start();主线程就安排一个线程【将连接进来的客户端封装到一个线程中】
* 流对象的不断读写操作......
* s.close();
* }
*/
package test;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPThreadTest {
public static void main(String[] args) throws IOException {
//将UploadServerOfPhoto代码修改
ServerSocket ss = new ServerSocket(10006);
while(true){
Socket s = ss.accept();
new Thread(new UploadTask(s)).start();
}
//ss.close();这里无需关闭,因为while无限循环
}
}
======================分割线====================================
package test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class UploadTask implements Runnable {
private Socket s;
private int count = 0;
public UploadTask(Socket s) {
this.s = s;
}
@Override
public void run() {
// 这里写的代码是每个客户端连接到服务端均要做的事情
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "......connected");
try {
InputStream in = s.getInputStream();
File dir = new File("c:\\pic");
if (!dir.exists())
dir.mkdirs();
File file = new File(dir, ip + ".bmp");
/*
* 有可能出现同一个客户端上传不止一个文件的情况,为了防止后一个文件将前一个覆盖,这里给文件名加上编号。(这就是
* 为什么迅雷下载同一个文件,第一个若叫xxx.bmp,第二个叫xxx(1).bmp的原因)
*/
if(file.exists())
file = new File(dir,ip+"("+(++count)+")"+".bmp");
FileOutputStream fos = new FileOutputStream(file);
byte[] bufIn = new byte[1024];
int lenIn = 0;
while ((lenIn = in.read(bufIn)) != -1) {
fos.write(bufIn, 0, lenIn);
}
OutputStream out = s.getOutputStream();
out.write("上传成功......".getBytes());
fos.close();
s.close();
} catch (IOException e) {
}
}
}