• java的网络编程


    1.流式套接字和数据报式套接字以及原始式套接字的区别

    流式套接字:面向连接,可靠的数据连接方式,数据无差错,无重复,完全按照发送顺序,可大量传输数据,传输完毕需要释放已经建立的连接,效率不高,遵循三次握手,发送信息,接受信息,反馈已经接受的信息。(TCP协议)

    数据报式套接字:无服务连接,数据以独立包的形式发送,不提供数据无差错,无重复保证,且接受是无序的,不需要建立连接,大小限制在64k之内,无需释放资源速度快。(UDP)协议

    原始式套接字:允许对较低层次协议,如ip的直接访问,监听网络流量和分析比较有用

    2.可用端口

    可用端口为1-65535,但是1-1024不建议使用,还有例如3306,8080等端口也相应的被占用

    3.dns域名解析过程

    首先查找的是浏览器缓存中是否有已经解析的域名地址,如果有,那么直接使用,这个域名解析过程结束,这个时间由ttl来设置,但是也受浏览器缓存大小的限制,缓存时间过长,ip地址变化找不到ip地址,导致域名不能正常解析,时间太短,那么导致每次访问网站都需要重新解析一次域名,如果在缓存中没有找到,那么会相应的在操作系统的缓存中选择是否有相应的解析ip地址解析结果,如果有那么久使用这个ip地址并返回,这里在以前的时候存在域名劫持,因为可以通过c:windowssystemsdriveretchosts 来指定一个解析的ip地址,win7后这个只能读而不能改,当然linux的配置文件/etc/name.conf中也可以修改达到同样的目的,当然也受到缓存时间的影响,假如前两个无法解决,那么会相应的发送到ldns(本地区的域名服务器,公司的服务器),这window下可以使用ipconfig查询,在linux下可以查相应的配置文件 /etc/resolv.conf  ,一般而言这个专门的域名解析性能都会比较好。一般会缓存域名解析的结果,也受缓存时间的控制,大约80%的域名解析都是在这里完成的,ldns主要承担了域名的解析工作,这里假如还是没有才会使用root server域名的解析工作,返回时一个逆过程,在dns解析的过程中主要在两个地方缓存结果,一个是ldns一个是本机,其中缓存控制是由缓存时间和缓存大小控制的,最大的缓存时间是ttl,ldns的缓存时间是我们很难由本地介入,本地的缓存可以使用 ipcongfig/flushdns,linux可以/etc/imit.d/nscd restart来清除缓存,当然在windows和linux下都可以使用nslookup来查看相应的解析结果

    4.InetAddress与SocketAddress

    InetAddress:表示带互联网协议

    SocketAddress:不带任何的协议

    public class InetAddressTest {
      public static void main(String[] args) throws UnknownHostException {
    	  InetAddress byName = InetAddress.getByName("localhost");
    	  System.out.println(byName.getHostName());
    	  System.out.println(byName.getHostAddress());
    		/*输出
    		 * localhost 
    		 * 127.0.0.1
    		 */
    }
    

     5.TCP(Socket与ServerSocket)

    备注:网络编程实质是网络版的io流

    @SuppressWarnings("all")
    public class ServerSocketAndSocketTest {
    	@Test
    	public void client() throws UnknownHostException, IOException {
    		Socket socket = null;
    		OutputStream outputStream = null;
    		try {
    			socket = new Socket("localhost", 9898);
    			outputStream = socket.getOutputStream();
    			outputStream.write("hello  你好!".getBytes());
    			outputStream.flush();
    		} finally {
    			if (outputStream != null) {
    				outputStream.close();
    			}
    			if (socket != null) {
    				socket.close();
    			}
    		}
    
    	}
    
    	@Test
    	public void server() throws IOException {
    		ServerSocket serverSocket = null;
    		Socket accept = null;
    		InputStream inputStream = null;
    		BufferedReader bufferedReader = null;
    		try {
    			serverSocket = new ServerSocket();
    			serverSocket.bind(new InetSocketAddress(9898));
    			// 阻塞式方法
    			accept = serverSocket.accept();
    			inputStream = accept.getInputStream();
    			bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
    			String str = null;
    			while ((str = bufferedReader.readLine()) != null) {
    				System.out.println(str);
    			}
    			// 这个可以使用getOutputStream()传输消息回去
    		} finally {
    			if (inputStream != null) {
    				inputStream.close();
    			}
    			if (bufferedReader != null) {
    				bufferedReader.close();
    			}
    			if (accept != null) {
    				accept.close();
    			}
    			if (serverSocket != null) {
    				serverSocket.close();
    			}
    		}
    
    	}
    }
    

     6.UDP(DatagramSocket与DatagramPacket)

    @SuppressWarnings("all")
    public class DatagramSocketAndDatagramPacketTest {
    	@Test
    	public void client() throws IOException {
    		DatagramSocket datagramSocket = null;
    		try {
    			datagramSocket = new DatagramSocket();
    			byte[] byt = "hello  你好".getBytes();
    			DatagramPacket datagramPacket = new DatagramPacket(byt, byt.length,
    					new InetSocketAddress("localhost", 9898));
    			datagramSocket.send(datagramPacket);
    		} finally {
    			if (datagramSocket != null) {
    				datagramSocket.close();
    			}
    		}
    
    	}
    
    	@Test
    	public void server() throws IOException {
    		DatagramSocket datagramSocket = null;
    		try {
    			datagramSocket = new DatagramSocket(9898);
    			byte[] byt = new byte[1024];
    			DatagramPacket datagramPacket = new DatagramPacket(byt, byt.length);
    			datagramSocket.receive(datagramPacket);
    			int length = datagramPacket.getLength();
    			byte[] data = datagramPacket.getData();
    			System.out.println(new String(data, 0, length, "utf-8"));
    		} finally {
    			if (datagramSocket != null) {
    				datagramSocket.close();
    			}
    		}
    
    	}
    }
    

    7.url

    public class URLTest {
         public static void main(String[] args) throws MalformedURLException {
    		  URL url = new  URL("https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&wd=%E7%99%BE%E5%BA%A6");
    		  System.out.println(url.getProtocol());//https
    		  System.out.println(url.getHost());//www.baidu.com
    		  System.out.println(url.getRef());//存在?为空,否则按实输出
    		  System.out.println(url.getPort());//-1  未定义默认的端口号
    		  System.out.println(url.getPath());//  /baidu
    		  System.out.println(url.getQuery());//锚点之后的内容
    	}
    }
    
    //爬取图片
    //有时会遇到403,这个在爬虫中
    public class URLDown { public static void main(String[] args) throws IOException { String path="http://www.umei.cc/meinvtupian/meinvxiezhen/20580.htm"; java.util.List<String> mapPath = getMapPath(path); for (String string : mapPath) { URL url = new URL(string); URLConnection openConnection = url.openConnection(); InputStream inputStream = openConnection.getInputStream(); FileOutputStream fileOutputStream = new FileOutputStream(url.getFile().substring(url.getFile().lastIndexOf("/")+1)); byte [] byts=new byte[1024]; int len=0; while((len=inputStream.read(byts))!=-1){ fileOutputStream.write(byts,0,len); } if(inputStream!=null){ inputStream.close(); } if(fileOutputStream!=null){ fileOutputStream.close(); } } } public static java.util.List<String> getMapPath(String path) throws IOException{ ArrayList<String> list = new ArrayList<>(); InputStream inputStream=null; BufferedReader bufferedReader=null; try { URL url = new URL(path); URLConnection openConnection = url.openConnection(); inputStream = openConnection.getInputStream(); //获取编码格式 String fileEncode = URLDown.getFileEncode(path); bufferedReader = new BufferedReader(new InputStreamReader(inputStream, fileEncode)); String str = null; String regex="http://i1.umei.cc/uploads/tu/201807.*.jpg"; Pattern compile = Pattern.compile(regex); while ((str = bufferedReader.readLine()) != null) { Matcher matcher = compile.matcher(str); while(matcher.find()){ //将符合要求的放入集合 list.add(matcher.group()); } } return list; } finally { if(bufferedReader!=null){ bufferedReader.close(); } if(inputStream!=null){ inputStream.close(); } } } public static String getFileEncode(String path) { /* * detector是探测器,它把探测任务交给具体的探测实现类的实例完成。 * cpDetector内置了一些常用的探测实现类,这些探测实现类的实例可以通过add方法 加进来,如ParsingDetector、 * JChardetFacade、ASCIIDetector、UnicodeDetector。 * detector按照“谁最先返回非空的探测结果,就以该结果为准”的原则返回探测到的 * 字符集编码。使用需要用到三个第三方JAR包:antlr.jar、chardet.jar和cpdetector.jar * cpDetector是基于统计学原理的,不保证完全正确。 */ CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance(); /* * ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于 * 指示是否显示探测过程的详细信息,为false不显示。 */ detector.add(new ParsingDetector(false)); /* * JChardetFacade封装了由Mozilla组织提供的JChardet,它可以完成大多数文件的编码 * 测定。所以,一般有了这个探测器就可满足大多数项目的要求,如果你还不放心,可以 * 再多加几个探测器,比如下面的ASCIIDetector、UnicodeDetector等。 */ detector.add(JChardetFacade.getInstance());// 用到antlr.jar、chardet.jar // ASCIIDetector用于ASCII编码测定 // detector.add(ASCIIDetector.getInstance()); // UnicodeDetector用于Unicode家族编码的测定 // detector.add(UnicodeDetector.getInstance()); java.nio.charset.Charset charset = null; URL url=null; try { url = new URL(path); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { charset = detector.detectCodepage(url); } catch (Exception ex) { ex.printStackTrace(); } if (charset != null) return charset.name(); else return null; }; }
    //多线程下载
    public class UrlThreadDown { public static void main(String[] args) throws IOException, InterruptedException { long start = System.currentTimeMillis(); String pathName = "https://qd.myapp.com/myapp/qqteam/tim/down/tim_pc.exe"; int threadNum = 3; CountDownLatch countDownLatch = new CountDownLatch(threadNum); ThreadDown threadDown = new ThreadDown(pathName, threadNum,countDownLatch); for (int i = 0; i < threadNum; i++) { new Thread(threadDown).start(); } countDownLatch.await(); long end = System.currentTimeMillis(); System.out.println(end-start); threadDown.fileConnect(); end = System.currentTimeMillis(); System.out.println(end-start); } } @SuppressWarnings("all") class ThreadDown implements Runnable { public List<String> list = new ArrayList<>(); private String pathName; private int threadNum; private int threadI; private int contentLength; CountDownLatch countDownLatch; public ThreadDown(String pathName, int threadNum,CountDownLatch countDownLatch) throws IOException { this.pathName = pathName; this.threadNum = threadNum; this.countDownLatch=countDownLatch; URL url=null; try { url = new URL(pathName); URLConnection openConnection = url.openConnection(); contentLength = openConnection.getContentLength(); } catch (Exception e) { System.out.println(pathName+"不正确"); } } @Override public void run() { try { down(); } catch (IOException e) { e.printStackTrace(); } } public void down() throws IOException { URL url = new URL(pathName); if(url==null) { return; } if(contentLength==-1){ System.out.println("大小未知"); return; } String fileName=url.getFile(); URLConnection openConnection = url.openConnection(); //在创建对象之后,建立连接之前,可指定各种选项(例如,doInput 和 UseCaches)。 //连接后再进行设置就会发生错误。连接后才能进行的操作(例如 getContentLength), //如有必要,将隐式执行连接。 int size = contentLength / threadNum + 1; BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try { String bytes = null; String substring = null; synchronized (this) { if (threadI < threadNum - 1) { bytes = "bytes=" + threadI * size + "-" + ((threadI + 1) * size-1); } else { bytes = "bytes=" + (contentLength - ((threadI - 1) * size-1)) + "-" + (contentLength-1); } substring = fileName.substring(fileName.lastIndexOf("/") + 1) + threadI; threadI++;
                       list.add(substring); }
                  //包括开头和结尾 openConnection.setRequestProperty("Range", bytes); bufferedInputStream = new BufferedInputStream(openConnection.getInputStream()); bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(substring)); int len = 0; while ((len = bufferedInputStream.read()) != -1) { bufferedOutputStream.write(len); } countDownLatch.countDown(); } finally { if (bufferedInputStream != null) { bufferedInputStream.close(); } if (bufferedOutputStream != null) { bufferedOutputStream.close(); } } } public void fileConnect() throws IOException { if(list.size()<=1){ return; } BufferedOutputStream bufferedOutputStream = null; try { Collections.sort(list); bufferedOutputStream = new BufferedOutputStream( new FileOutputStream(list.get(0).substring(0, list.get(0).length() - 1))); for (String string : list) { BufferedInputStream bufferedInputStream = null; try { bufferedInputStream = new BufferedInputStream(new FileInputStream(string)); int len = 0; while ((len = bufferedInputStream.read()) != -1) { bufferedOutputStream.write(len); } } finally { if (bufferedInputStream != null) { bufferedInputStream.close(); } } } } finally { if (bufferedOutputStream != null) { bufferedOutputStream.close(); } } } }

     备注:使用skip循环下载并不适用网络下载,因为网络存在阻塞,出于各种原因,skip 方法最终跳过的字节数可能更少一些,甚至可能为 0。如果 n 为负,则抛出 IOException,例如如下,可以下载Apache下的本地文件,但是网上并不适用,available()方法,返回不收阻塞的输入流

    class ThreadDown2 implements Runnable {
    	public List<String> list = new ArrayList<>();
    	private String pathName;
    	private int threadNum;
    	private int threadI;
    	private int contentLength;
    	CountDownLatch countDownLatch;
    	public ThreadDown2(String pathName, int threadNum,CountDownLatch countDownLatch) throws IOException {
    		this.pathName = pathName;
    		this.threadNum = threadNum;
    		this.countDownLatch=countDownLatch;
    		URL url=null;
    		try {
    			url = new URL(pathName);
    			URLConnection openConnection = url.openConnection();
    			contentLength = openConnection.getContentLength();
    			System.out.println(contentLength);
    		} catch (Exception e) {
    			System.out.println(pathName+"不正确");
    		}
    	}
    
    	@Override
    	public void run() {
    		try {
    			down();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	public void down() throws IOException {
    		URL url = new URL(pathName);
    		if(url==null) {
    			return;
    		}
    		if(contentLength==-1){
    			System.out.println("大小未知");
    			return;
    		}
    		String fileName=url.getFile();
    		URLConnection openConnection = url.openConnection();
    		//在创建对象之后,建立连接之前,可指定各种选项(例如,doInput 和 UseCaches)。
    		//连接后再进行设置就会发生错误。连接后才能进行的操作(例如 getContentLength),
    		//如有必要,将隐式执行连接。 
    		int size = contentLength / threadNum + 1;
    		InputStream inputStream=null;
    		FileOutputStream fileOutputStream =null;
    		try {
    			int startPosition=0;
    			int endPosition=0;
    			String substring = null;
    			synchronized (this) {
    				startPosition=threadI * size;
    				if (threadI < threadNum - 1) {
    					endPosition=(threadI+1)* size;
    				} else {
    					endPosition=contentLength;
    				}
    				substring = fileName.substring(fileName.lastIndexOf("/") + 1) + threadI;
    				threadI++;
    				list.add(substring);
    			}
    			String substring2 = substring.substring(substring.length()-1);
    			if(endPosition-startPosition==size){
    				inputStream = openConnection.getInputStream();
    				fileOutputStream = new FileOutputStream(substring);
    				inputStream.skip(Integer.valueOf(substring2)*size);
    				System.out.println(substring+":"+Integer.valueOf(substring2)*size+":"+(Integer.valueOf(substring2)*size+size));
    				byte[] byts = new byte[8192];
    				for (int i = 0; i <= size / 8192; i++) {
    					if (i < size / 8192 ) {
    						inputStream.read(byts);
    						fileOutputStream.write(byts, 0, 8192);
    					} else {
    						inputStream.read(byts);
    						fileOutputStream.write(byts, 0, size%8192);
    					}
    				}
    			} else {
    				inputStream = openConnection.getInputStream();
    				fileOutputStream = new FileOutputStream(substring);
    				inputStream.skip(Integer.valueOf(substring2)*size);
    				byte[] byts = new byte[8192];
    				System.out.println(substring+":"+Integer.valueOf(substring2)*size+":"+(Integer.valueOf(substring2)*size+contentLength % size));
    				System.out.println(111111111);
    				for (int i = 0; i <= contentLength % size / 8192; i++) {
    						int read = inputStream.read(byts);
    						if(read!=-1){
    							fileOutputStream.write(byts, 0, read);
    						}
    					}
    				}
    			countDownLatch.countDown();
    		} finally {
    			if (inputStream != null) {
    				inputStream.close();
    			}
    			if (fileOutputStream != null) {
    				fileOutputStream.close();
    			}
    		}
    	}
    
    	public void fileConnect() throws IOException {
    		if (list.size() <= 1) {
    			return;
    		}
    		BufferedOutputStream bufferedOutputStream = null;
    		try {
    
    			bufferedOutputStream = new BufferedOutputStream(
    					new FileOutputStream(list.get(0).substring(0, list.get(0).length() - 1)));
    			for (String string : list) {
    				BufferedInputStream bufferedInputStream = null;
    				try {
    					bufferedInputStream = new BufferedInputStream(new FileInputStream(string));
    					int len = 0;
    					while ((len = bufferedInputStream.read()) != -1) {
    						bufferedOutputStream.write(len);
    					}
    				} finally {
    					if (bufferedInputStream != null) {
    						bufferedInputStream.close();
    					}
    				}
    			}
    		} finally {
    			if (bufferedOutputStream != null) {
    				bufferedOutputStream.close();
    			}
    		}
    	}
    }
    
  • 相关阅读:
    centos7的网络设置
    day1学习
    举例讲解Linux系统下Python调用系统Shell的方法
    Python引用模块和查找模块路径
    详解Python中的循环语句的用法
    [cf1566H]Xorquiz
    [luogu5180]支配树
    [atAGC055D]ABC Ultimatum
    [cf1552H]A Serious Referee
    [gym102538H]Horrible Cycles
  • 原文地址:https://www.cnblogs.com/gg128/p/9409546.html
Copyright © 2020-2023  润新知