27-网络编程-19-网络编程(TCP协议-练习-服务端多线程技术)

/*
 * 前两个视频客户端上传图片给服务端的若干问题:
 * 
 * 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) {

		}
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值