描述:
(1)jdk自带线程池见 JDK自带线程池配置
(2)此上传文件服务器中上传文件的后缀名通过第一段缓冲字符流传递,此缓冲字符流大小为1024,在文件接收端以1024接收、处理。
1、服务器代码如下(使用jdk自带线程池):
1 /**
2 * 服务器处理多线程问题
3 *
4 * 1.因为服务器是要很多人访问的,因此里面一定要用多线程来处理,不然只能一个人一个人的访问,那还叫Y啥服务器
5 *
6 * 2,拿上面这个文件上传的例子来说,它将每个连接它的用户封装到线程里面去,把用户要执行的操作定义到 run 方法里面
7 * 一个用户拿一个线程,拿到线程的就自己去执行,如果有其它用户来的时候,再给新来的用户分配一个新的线程 这样就完成了服务器处理多线程的问题 3.
8 * 在服务器与客户端互传数据时,我们要特别注意的是,防止两个程序造成 死等的状态,一般原因有以下:
9 *
10 * 1. 客户端向数据端发送数据时,当发送的是字符时,第次以一行来发送,而服务端在读取的时候,也是以 一行来读取,readLine()
11 * 而发送的时候往往只是发送换行以行的内容,而不能发换行也发送过去, 那么服务端在读取的时候就不读取不到换行 ,那么 readLine() 就不会停止 2.
12 * 客户端发送数据时,如果处理的是用 字符流 或是缓冲流的话,一定要记得刷新流,不然的话,数据就会发不出来 3 在用IO 读取文件里面的数据然后发送到服务端
13 * 时,当家读取文件 while(in.read()) 读取文件结束时,而在 服务端的接收程序
14 * while(sin.read())不会接到一个发送完毕的提示,所以会一直等待下去,所以我们在处理这
15 * 个问题的时候,还要将其发送一个文件读取结束的标志,告诉接收端文件已经读取完结,不要再等待了 而socket 里面给我们封装了 shutdownInput
16 * shutdownOutput 两个操作,此可以关闭 流,两样也可以起到告诉 接收方文件传送完毕的效果
17 *
18 *
19 *
20 * */
21 public class Server {
22
23 private static Logger logger = LoggerFactory.getLogger(Server.class);
24 private static final Integer PORT = 2222;
25
26
27 public static void main(String args[]) throws Exception {
28
29 ServerSocket server = new ServerSocket(PORT);
30
31 logger.info("服务器启动:::端口号为:{}",PORT);
32 ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 300, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(3),
33 new ThreadPoolExecutor.CallerRunsPolicy());
34
35 while (true) {
36
37 Socket client = server.accept();
38 executor.execute(new UploadThread(client));
39 // new Thread(new UploadThread(client)).start();
40 }
41
42 }
43 }
2、上传文件代码如下:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
|
3、接收文件代码如下:
package cn.iautos.manager.test.load;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.net.Socket;public class UploadThread implements Runnable // 将上传封装到线程里
{
private Socket client;public UploadThread(Socket s) {
this.client = s;
}public void run() {
// String ip = client.getInetAddress().getHostAddress(); // 得到 IP地址
try {
BufferedInputStream sin = new BufferedInputStream(client.getInputStream()); // Socket 读取流
byte b[] = new byte[1024];
int l = sin.read(b);
String line = new String(b, 0, l).split("\n")[0];
System.out.println("--------文件后缀为------"+line);File file = new File("E:\\loadServer\\" + ImgUtils.getImgName()
+ line);
BufferedOutputStream fout = new BufferedOutputStream(
new FileOutputStream(file)); // 文件输出流int len = 0;
// 开始从网络中读取数据
while (true) {
len = sin.read(b);
if(len != -1){
fout.write(b, 0, len);
}else{
break;
}
// System.out.println("--------------"+new String(buf,0,len));
}
PrintStream sout = new PrintStream(client.getOutputStream());
sout.write("发送成功".getBytes());
// sout.flush(); //虽然是字节流,但其用的是BufferedOutputStream
fout.close();
sin.close();
sout.close();
} catch (Exception ex) {
System.out.println();
ex.printStackTrace();}
}
}