当我们编写网络编程基础程序时,当遇到服务端若为单线程时往往会有局限性,当A客户端连接上后,被服务端获取到,服务端执行具体流程,此时若遇到B客户端来连接,B客户端只有等待。因为服务端还没有处理完A客户端的请求,还要循环回到执行下次的accept才可接收,所以暂时获取不到B客户端对象。那么,为了可以让客户端同时并发访问服务端,那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求:
那么我们应该如何定义线程呢?
只要明确了每一个客户端执行的代码即可,将该代码存入到run方法中(注意:客户端执行的代码是在服务端中的哦!):
接下来使用客户端向服务端上传png格式图片代码举例:
- import java.io.*;
- import java.net.*;
- class Text_Client {//定义客户端
- public static void main(String[] args)throws Exception {//为防止出现传输异常,先抛出异常
- if (args.length!=1){//判断是否上传了文件
- System.out.println("请选择一个png格式的图片:");
- return;
- }
- File file=new File(args[0]);
- if (!(file.exists()&&file.isFile()){//判断文件是否存在或者是否为文件
- System.out.println("该文件有问题,要么不存在,要么就不是文件");
- return;
- }
- if(!(file.getName().endsWith(".png"))){//是否为png格式图片
- System.out.println("图片格式错误,请重新选择");
- return;
- }
- if (file.length()>1024*1024*5){//防止传输文件大小过大
- System.out.println("文件过大");
- return;
- }
- Socket s=new Socket("192.168.1.105",10007);//创建TCP服务,并指定ip和端口
- FileInputStream fis=new FileInputStream(file);
- OutputStream out=s.getOutputStream();//获取输出流
- int leng=0;
- byte[] buf =new byte[1024];
- while((leng=fis.read(buf))!=-1){
- out.write(buf,0,leng);
- }
- s.shutdownOutput();//关闭客户端输出流,相当于给流中添加了一个结束标记-1
- InputStream In=s.getInputStream();//获取输入流,接收服务端传输过来的数据
- byte[] bufIn=new byte[1024];
- int num=In.read(bufIn);
- System.out.println(new String(bufIn,0,num));//打印数据
- fis.close();
- s.close();//关闭资源
- }
- }
- class PicThread implements Runnable{//定义线程实现Runnable接口
- private Socket s;
- PicThread(Socket s){
- this.s=s;
- }
- public void run(){//覆盖run方法
- int count=0;
- String ip =s.getInetAddress().getHostAddress();//获取ip
- try{
- System.out.println(ip+"...connected");
- InputStream In=s.getInputStream();//获取输入流
- File file=new File(ip+"("+(++count)+")"+".png");
- while(file.exists()){//保存图片
- file=new File(ip+"("+(++count)+")"+".png");
- }
- FileOutputStream fos=new FileOutputStream(file);
- byte[] buf=new byte[1024];
- int leng=0;
- while((leng=In.read(buf))!=-1){
- fos.write(buf,0,leng);
- }
- OutputStream out=s.getOutputStream();<span style="line-height: 30.7999992370605px;">//获取输出流反馈信息</span>
- out.write("上传成功".getBytes());
- fos.close();
- s.close();//关闭资源
- }
- catch (Exception e){
- throw new RuntimeException(ip+"上传失败");
- }
- }
- }
- class Text_Server {//定义服务端创立线程
- public static void main(String[] args)throws Exception {
- ServerSocket ss=new ServerSocket(10007);
- while(true){
- Socket s=ss.accept();
- new Thread(new PicThread(s)).start();
- }
- //ss.close(); 不需要关闭ss资源,因为要持续接收文件
- }
- }
复制代码 以上程序可以实现多个客户端对服务端数据的上传,服务端把每次上传的文件以ip+数字循环命名,防止文件名重复。
|
|