• java多线程文件上传服务器


     描述:

    (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、上传文件代码如下:

    package cn.iautos.manager.test.load;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class Upload {
    	
    	public static void main(String args[]) throws Exception {
    		
    		Timer timer = new Timer();
    		timer.schedule(new TimerTask() {
    			public void run() {
    				try {
    					System.out.println("--------开始上传文件-------");
    					loadMethod();
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		}, 0, 500);
    	}
    	
    	public static void loadMethod() throws Exception{
    
    		String name = "E:\qqq.jpg";
    		Socket client = new Socket("127.0.0.1", 2222);
    		File file = new File(name);
    		
    		String imgSuffix = ImgUtils.getImgSuffix(name);
    		
    		BufferedInputStream fin = new BufferedInputStream(new FileInputStream(
    				file)); // 文件读取流
    		PrintStream sout = new PrintStream(client.getOutputStream(), true); // 得到socket流
    		/**
    		 * 添加后缀名
    		 */
    		byte[] b = new byte[1024];
    			byte[] bb = (imgSuffix+"
    ").getBytes();
    			for(int j = 0;j<bb.length;j++){
    				b[j] = bb[j];
    			}
    		sout.write(b,0,b.length);
    		
    		int len = 0;
    		while ((len = fin.read(b)) != -1) {
    			sout.write(b, 0, len);
    			System.out.println(len + "...发送中");
    		}
    		client.shutdownOutput();
    		BufferedInputStream sin = new BufferedInputStream(client
    				.getInputStream());
    		len = sin.read(b);
    		System.out.println(len);
    		System.out.println(new String(b, 0, len));
    		sin.close();
    		sout.close();
    		fin.close();
    
    	
    		
    	}
    }
    

    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("
    ")[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();
    
            }
    
        }
    }
  • 相关阅读:
    在.net C#里怎样调用非托管动态库函数dll?
    Visual C#中的MDI编程
    c#图形装置接口
    粗糙集理论介绍
    Using .NET DataSet in Flex 2
    图象光照研究路线
    基于光照模型应用前景
    使用netsh.exe配置TCP/IP
    vb.net 防止MDI子窗体被多次实例化的四种方法
    一定概率选中某一字母
  • 原文地址:https://www.cnblogs.com/xuzhenmin/p/3777626.html
Copyright © 2020-2023  润新知