黑马程序员——Java基础——网络编程(客户端并发上传图片)

------- android培训、java培训、期待与您交流! ----------


对这部分的学习,自己理解为就相当于中国的一句老话:礼尚往来。

想要从掌握多种资源的人手里获取资源,自己需要先给予回报。简单流程就是:

需求者:

1、对资源有需求;

2、想法拜访资源拥有者,到某个地方购买礼物,投其所好。

3、通过关系介绍,建立渠道;

4、通过渠道将礼物送出;

资源拥有者:

5、收到礼物;

6、找寻自已已有的资源;

7、获取需求者建立的渠道;

8、通过渠道,将资源传给需求者;

需求者:

9、联系自己建立的渠道;

10、拿到资源拥有者传递的资源。

11、渠道关闭;永久不用,或下次继续利用。

资源拥有者:

12、可以不再提供资源,或者继续。


按照我自己理解的方式写代码始终不会乱,如果将客户端代码写完后,再写客户端往往会觉得有点里不清楚。

以下是视频中讲的专业语句。

TCP协议客户端并发上传图片的步骤:
客户端:

1、创建Socket服务并指定要连接的主机和端口;
2、建立读取流对象,读取文件数据;
3、获取Socket流中的输出流,将数据写到流中,通过网络发送到服务端;
4、使用socket对象中shutdownOutput方法向服务端发送一个结束标记;
5、获取Socket流中的读取流,读取服务端返回的数据,打印在客户端平台上;
6、关闭读取流资源,关闭客户端,

服务端:
1、建立服务端的Socket服务,并监听一个端口;
2、在循环体内,获取连接过来的客户端对象,通过ServerSocket的accept方法获取,此方法为阻塞式方法;
并新建一个线程,使每一个客户端都拥有自己的线程,在线程内进行读取和输出流数据,将流操作封装在一个类中;
3、此类实现Runnable接口,实现run方法,初始化时传连接过来的客户端对象,通过ServerSocket的accept方法获取,此方法为阻塞式方法;
4、客户端如果发过来数据那么服务端使用对应的客户端对象并获取到该客户端对象的读取流来读取发过来的数据;
5、建立输出流对象,将读取流中的数据写到服务端上。
6、关闭输出流,关闭获取的客户端对象。
个人学习心得:
我在测试时,当以插入网线时连接我的IPv4的IP地址为主机时,无法传输成功,当拔掉网线连接127.0.0.1为主机的时候可以,插上网线还是这个IP地址,就不行了,我采用了第三种IP地址,即本机的本地IPv6地址的时候无论插入网线还是拔掉网线都可以传输成功。不过我还不知道为什么。有知道的可以帮忙解释一下,但是这样的话对本程序会出现一个问题,如果我以IP地址为文件名,存储客户端上传的文件时,会出现异常,因为IPv6中含有违反文件命名的非法字符,所以我采用了IP名的子字符串。


import java.net.*;
import java.io.*;

/*
需求:实现客户端多线程并发向服务端上传图片。
*/
class PicClient2
{
        public static void main(String[] args) throws Exception
        {
                //此处我没有做那么多的判断
                File file = new File(args[0]);
				//创建Socket服务,并指定要连接的主机和端口
                Socket s = new Socket("fe80::58fd:ab7f:707d:dc6a%15",10008);
                
				//创建字节读取流,到指定地方买礼物。
                FileInputStream fis = new FileInputStream(file);
                
				//获取Socket流中的输出流。将数据写到流中,通过网络发送到服务端;
				//通过某个渠道送礼。
                OutputStream out = s.getOutputStream();
                
                byte[] buf = new byte[1024];
                int len = 0;
				//读取文件数据,写入输出流,将礼物发出的过程。
                while((len = fis.read(buf)) != -1)
                {
                        out.write(buf,0,len);
                }
                //采用标准方式,关闭客户端的输出流,相当于给流中加入一个结束标记-1。
                s.shutdownOutput();
                
				//获取Socket流中的读取流,将服务端发来的数据反馈到客户端。
                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
{
		//在创建对象时既传入Socket服务
        private Socket s;
        PicThread(Socket s)
        {
                this.s = s;
        }
		//实现run方法
        public void run()
        {
                int count = 1;
                String ip = s.getInetAddress().getHostAddress();
                String subip = ip.substring(1,4);
                try
                {                        
                        System.out.println(ip +".....connected");
                        
                        InputStream in = s.getInputStream();
                        
                        //此处为讲课中的一点失误,按照正常来说先有***.jpg文件存在
                        //然后如果再有的话上传的话再有***(n).jpg.
                        File file = new File(subip+".jpg"); //此行代码应该这么写。
                        while(file.exists())
                                file = new File(subip+"("+(count++)+")"+".jpg");
                        
                        
                        
                        FileOutputStream fos = new FileOutputStream(file);
                        byte[] buf = new byte[1024];
                        
                        int len = 0;
                        while((len = in.read(buf))!= -1)
                        {
                                fos.write(buf,0,len);
                        }
                        
                        OutputStream out = s.getOutputStream();
                        
                        out.write("load Success".getBytes());
                        
                        fos.close();
                        s.close();
                }
                catch(Exception e)
                {
                        throw new RuntimeException(ip+"上传失败");
                }
        }
}
class PicServer2
{
        public static void main(String[] args) throws Exception
        {
                ServerSocket ss = new ServerSocket(10008);
                //在每次传入服务时都建立自己的线程。
                while(true)
                {
                        Socket s = ss.accept();
                        new Thread(new PicThread(s)).start();
                        
                }                        
        }
}

----------android培训java培训、java学习型技术博客、期待与您交流!------------  

你可能感兴趣的:(黑马程序员——Java基础——网络编程(客户端并发上传图片))