码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA网络编程

时间:2016-01-16 23:40:17      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:

学习资料:《java疯狂讲义》

网络已经像空气和水一样,成为了人们日常生活离不开的东西。网络也是开发中不可或缺的知识。我们学习理论很重要,将理论运用于实践更能加强对理论的理解,最后软件开发的生产力也将随之提高。

在学校里学的那本《计算机网络》,已经忘得差不多了。。。。

1.网络基础

网络模型:

技术分享

ip(地址):唯一标识网络中的一个通信实体(主机、打印机、路由器端口等等)

TCP:Transmission Control Protocol,传输层协议。

端口(房间号):一个通信实体可以有多个通信程序同时提供网络服务,每一个通信服务占用一个端口。

URL(locators):代表互联网里的统一资源定位器。可以指向文件、目录、或是更为复杂的对象引用,如数据库或搜索引擎的查询。URL格式如下:

protocol://host:port/resourceName

URI(identifiers):Java的URI不能用于定位任何资源,它的唯一作用就是解析。

TCP/IP网络模型: TCP和IP协议互补,结合使用。原理是在网络两端分别建立socket通信端口,实现虚拟链路,并通过产生的IO通信。

 

2.java的基本网络支持

java.net包【可以对照API学习】:http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4

InetAddress类代表ip地址(没有加入端口): 它并没有提供太多的方法,但是该类是网络通信的基础,经常被大量使用。

技术分享
public class InetAddressTest {
    public static void main(String[] args) throws IOException
    {
        InetAddress ip =InetAddress.getByName("www.crazyit.org");
        System.out.println(ip.isReachable(2000));
        System.out.println(ip.getHostName());
        System.out.println(ip.getHostAddress());
        InetAddress local=InetAddress.getLocalHost();
        System.out.println(local);
        System.out.println(local.getHostAddress());
    }

}
View Code

URLEncoder和URLDecoder类:用于完成非西欧字符串(如中文)字符串和application/x-www-form-urlencoded MIME字符串之间的转换。

如:中国<----->%E4%B8%AD%E5%9B%BD (不同编码方式GBK,utf-8,转换结果不一样)

技术分享
public class URLDecoderTest {

    public static void main(String[] args) throws UnsupportedEncodingException {
        // TODO Auto-generated method stub
        String keyWord=URLDecoder.decode("%E4%B8%AD%E5%9B%BD","utf-8");
        System.out.println(keyWord);
        String urlStr = URLEncoder.encode("中国", "GBK");
        System.out.println(urlStr);
    }
View Code

输出结果:

中国
%D6%D0%B9%FA

URL、URLConnection和URLPermission类:

例1:实现一个简单的多线程下载工具类

从 http://www.crazyit.org/ 下载一个名为"ios.png”的图片。

技术分享
/*实现一个多线程下载工具类*/
public class DownUtil {
    private String path;
    private String targetFile;
    private int threadNum;
    private DownThread[] threads;
    private int fileSize;
    
    public DownUtil(String path, String targetFile, int threadNum) {
        this.path = path;
        this.threadNum = threadNum;
        threads = new DownThread[threadNum];//这里没有初始化的话会报错NULL POINTER
        this.targetFile = targetFile;
        
    }

    public void download() throws Exception
    {
        URL url = new URL(path);
        HttpURLConnection conn =(HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5*1000);
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Accept","image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
                +"application/x-shockwave-flash, application/xaml+xaml, "
                +"application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                +"application/x-ms-application, application/vnd.ms-excel, "
                +"application/vnd.ms-powerpoint, application/msword, */*");
        conn.setRequestProperty("Accept-Language",  "zh-CN");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setRequestProperty("Connection", "Keep-Alive");
        
        //得到文件大小
        fileSize=conn.getContentLength();
        conn.disconnect();
        int currentPartSize=fileSize/threadNum+1;
        RandomAccessFile file=new RandomAccessFile(targetFile,"rw");
        System.out.println(file.toString());
        //设置本地文件大小
        file.setLength(fileSize);
        file.close();
        for(int i =0;i<threadNum;i++)
        {
            //计算每个线程下载的开始位置
            int startPos=i*currentPartSize;
            //每个线程使用一个RandomAccessFile进行下载
            RandomAccessFile currentPart=new RandomAccessFile(targetFile,"rw");
            //定义该线程的下载位置
            currentPart.seek(startPos);
            threads[i] = new DownThread(startPos,currentPartSize,currentPart);
            //启动下载线程
            threads[i].start();
            
        }
        
    }
    
    public double getCompleteRate()
    {
        int sumSize=0;
        for(int i=0;i<threadNum;i++)
        {
            sumSize+=threads[i].length;
        }
        return sumSize*1.0/fileSize;
    }
    private class DownThread extends Thread{
        //当前线程的下载位置
        private int startPos;
        //当前线程负责下载的文件大小
        private int currentPartSize;
        //当前线程需要下载的文件块
        //该线程已下载的字节数
        public int length;
        private RandomAccessFile currentPart;//RandomAccessFile类
        public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
            super();
            this.startPos = startPos;
            this.currentPartSize = currentPartSize;
            this.currentPart = currentPart;
        }
        public void run()
        {
            try
            {
                URL url = new URL(path);
                HttpURLConnection conn =(HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5*1000);
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept","image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
                        +"application/x-shockwave-flash, application/xaml+xaml, "
                        +"application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                        +"application/x-ms-application, application/vnd.ms-excel, "
                        +"application/vnd.ms-powerpoint, application/msword, */*");
                conn.setRequestProperty("Accept-Language",  "zh-CN");
                conn.setRequestProperty("Charset", "UTF-8");
                
                InputStream inStream=conn.getInputStream();
                //跳过startPos个字符,表示该线程只下载自己负责的那部分文件
                inStream.skip(this.startPos);
                byte[] buffer = new byte[1024];
                int hasRead=0;
                //读取网络数据,并写入本地文件
                while(length<currentPartSize && (hasRead=inStream.read(buffer))!=-1)
                {
                    currentPart.write(buffer, 0, hasRead);
                    length+=hasRead;
                }
                currentPart.close();
                inStream.close();
                
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }        
    }
}
View Code

测试下载工具类

技术分享
/*测试下载工具类*/
public class MultiThreadDown {
    public static void main(String[] args) throws Exception
    {
        final DownUtil downUtil = new DownUtil("http://www.crazyit.org/"
                +"attachments/month_1403/1403202355ff6cc9a4fbf6f14a.png","ios.png",5);
        downUtil.download();
        new Thread(() ->{
            while(downUtil.getCompleteRate()<1)
            {
                System.out.println("已完成:"+downUtil.getCompleteRate());
                try
                {
                    Thread.sleep(1000);
                }
                catch(Exception ex){}
            }
        }).start();
    }

}
View Code

关于断点下载,加一个配置文件,该配置文件分别记录每个线程已经下载到哪个字节,当断开网络后再次开始下载时,每个线程根据配置文件里记录的位置向后下载即可。

 

例2:向Web站点发送GET请求、POST请求,并从Web站点取得响应。

技术分享
public class GetPostTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String s =GetPostTest.sentGet("http://localhost:8080/index.jsp", null);
        System.out.println(s);
        String s1=GetPostTest.sendPost("http://localhost:8080/abc/login.jsp", "name=crazyit.org&pass=leegang");
        System.out.println(s1);

    }
/*向指定URL发送GET方式的请求
@param url
@param param 请求参数name1=value2&name2=value2的形式
@return URL 远程资源的响应
*/
    public static String sentGet(String url,String param)
    {
        String result="";
        String urlName=url+"?"+param;
        try
        {
            URL realUrl=new URL(urlName);
            URLConnection conn=realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0(compatible; MSIE 6Map<K, V> Windows NT 5.1; SV1)");
            conn.connect();
            Map<String, List<String>> map=conn.getHeaderFields();
            for(String key:map.keySet())
            {
                System.out.println(key+"-->"+map.get(key));
            }
            try
            (
                //定义bufferedReaders输入流来读取URL的响应
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream(),"utf-8")))
            {
                String line;
                while((line=in.readLine())!=null)
                {
                    result+="\n"+line;
                }
                
            }
            
        }
        catch(Exception e)
        {
            System.out.println("发送GET请求出现异常!  "+e);
            e.printStackTrace();
        }
        return result;
    }
/*    向指定URL发送POST方式的请求
    @param url 
    @param param
    @return URL
    */
    public static String sendPost(String url, String param)
    {
        String result="";
        try
        {
            URL realUrl = new URL(url);
            URLConnection conn= realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0(compatible; MSIE 6Map<K, V> Windows NT 5.1; SV1)");
            //发送post请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            try
            (
                PrintWriter out = new PrintWriter(conn.getOutputStream()))
            {
                out.print(param);
                //flush输出流的缓冲
                out.flush();
            }
            try
            (
                //定义bufferedReaders输入流来读取URL的响应
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream(),"utf-8")))
            {
                String line;
                while((line=in.readLine())!=null)
                {
                    result+="\n"+line;
                }
                
            }
        }
            catch(Exception e)
            {
                System.out.println("发送GET请求出现异常!  "+e);
                e.printStackTrace();
            }
            return result;
        }
}

        
View Code

暴力破解:不停变换用户名和密码提交给登录站点,直至返回成功。

 

Socket、ServerSocket类

例子:实现一个简单的socket通信

技术分享
public class Server {
    public static void main(String[] args) throws IOException
    {
    ServerSocket ss = new ServerSocket(30000);
    while(true)
    {
        Socket s =ss.accept();
        PrintStream ps= new PrintStream(s.getOutputStream());
        ps.println("新年快乐!");
        ps.close();
        s.close();
    }
    }
}
View Code
技术分享
public class Client {

    public static void main(String[] args) throws UnknownHostException, IOException {
        // TODO Auto-generated method stub
        Socket socket=new Socket("127.0.0.1",30000);
        BufferedReader br = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
        String line=br.readLine();
        System.out.println(line);
        br.close();
        socket.close();

    }

}
View Code

加入多线程:每个客户通过键盘键入一些内容后按回车键,即可在控制台上收到刚刚输入的内容,粗略地实现了一个C/S结构的聊天室的功能。

技术分享
public class MyServer {
    //定义保存所有socket的arraylist,并将其包装为线程安全的
    public static List<Socket> socketList =Collections.synchronizedList(new ArrayList<>());
    public static void main(String[] args) throws IOException
    {
        ServerSocket ss= new ServerSocket(30001);
        while(true)
        {
            //此代码会阻塞,一直等待别人的连接
            Socket s =ss.accept();
            socketList.add(s);
            //每当客户端连接后启动一个serverThread线程为该客户端服务
            new Thread(new ServerThread(s)).start();
            
        }
    }
    

}
View Code
技术分享
public class ServerThread implements Runnable{
    Socket s =null;
    BufferedReader br = null;
    public ServerThread(Socket s) throws IOException
    {
        this.s=s;
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        
    }
    public void run()
    {
        try
        {
            String content =null;
            while((content=readFromClient())!=null)
            {
                //遍历socket,将读到的内容向每个socket发一次
                for(Socket s:MyServer.socketList)
                {
                    PrintStream ps = new PrintStream(s.getOutputStream());
                    ps.println(content);
                }
            }
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
    private String readFromClient()
    {
        try
        {
            return br.readLine();
        }
        catch(IOException e)
        {
            MyServer.socketList.remove(s);
        }
        return null;
    }

}
View Code
技术分享
public class MyClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
        // TODO Auto-generated method stub
        Socket s = new Socket("127.0.0.1",30001);
        new Thread(new ClientThread(s)).start();
        PrintStream ps = new PrintStream(s.getOutputStream());
        String line=null;
        BufferedReader br = new BufferedReader(
                new InputStreamReader(System.in));
        while((line=br.readLine())!=null)
        {
            ps.println(line);
        }

    }

}
View Code
技术分享
public class ClientThread implements Runnable{
    private Socket s;
    BufferedReader br =null;
    public ClientThread(Socket s) throws IOException
    {
        this.s=s;
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        
    }
public void run()
{
    try
    {
        String content=null;
        while((content=br.readLine())!=null)
        {
            System.out.println(content);
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

}
View Code

记录用户(客户端)信息,实现私聊功能

<!----未完待续----!>

 

JAVA网络编程

标签:

原文地址:http://www.cnblogs.com/flyingbee6/p/5136544.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!