您的位置:首页 > 理论基础 > 计算机网络

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

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

}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: