JAVA网络编程

来源:互联网 发布:ndk r9d mac 编辑:程序博客网 时间:2024/05/21 12:05

ava

网络基本知识:

在java中网络程序有两种协议:TCP和UDP,TCP通过握手协议进行可靠的连接,UDP则是不可靠连接。

IP地址:用于标记一台计算机的身份证。

IP地址由网络地址(确定网络)和主机地址(网络中的主机)组成。

子网掩码:为了区分网络地址和主机地址。

IP地址分为A类地址、B类地址、C类地址(常用)、D类地址、E类地址。

127.0.0.1(localhost)是本机地址。

IPV4和IPV6

IPV4使用4个十进制数表示,即32位二进制。

SMTP是简单邮件传输协议,端口号是25.


telnet用于连接远程计算机或者因特网计算机提供的服务。每个服务都会设定一个端口。

给出类似     telnet ip    port    即可和特定的服务进行通信

如果要连接因特网的服务,不仅要给出端口,还要给出计算机的名称,只有给出IP地址和端口号时,才能够请求服务,并接收到应答。


URL和URI

URI:统一资源标识符,用于标识一个web资源,包含了两个部分。

(1)URL:统一资源定位符。能够精确的定位数据的URI

(2)URN:统一资源名称。除了URL的URI

在java中URI和URL是分开的两个类,URI类专门用于解析,URL用于通信。

URL

1.URI分类

绝对和相对:

(1)绝对URI是指有确定的协议。比如http,ftp。后面以/进行分隔

(2)相对URI是没有scheme的。

透明和不透明:

(1)不透明URI是不能够被解析的URI。不透明URI是绝对URI。scheme后面的部分不是以/进行分割。

分层和不分层:

(1)分层是绝对透明URI或相对URI。

所有的网页端口都是80.

2.URI的作用:

(1)解析

URI的格式:

[scheme:]scheme-specific-part[#fragment]

scheme表示用的协议,可以是http\https\ftp\file等。

scheme-specific-part是其余部分。

进一步细分:

[scheme:][//authority][path][?query][#fragment]

常用方法:

  • getScheme()获得scheme;
  • getSchemeSpecificPart()
  • getPath()
  • getAuthority()

(2)相对标识符和绝对标识符的转换

resolve和relative函数。

示例代码:

任务1:取得特定网址的html代码。

任务2:分析地址信息。

任务3:绝对地址和相对地址转换

[java] view plaincopy
  1. package org.core;  
  2.   
  3. import java.net.*;  
  4. import java.util.*;  
  5.   
  6. public class URLTest1 {  
  7.   
  8.     public static void main(String[] args) throws Exception {  
  9.         URL url = new URL("http://www.ecnu.edu.cn");  
  10.         Scanner in = new Scanner(url.openStream());  
  11.         while (in.hasNextLine()) {  
  12.             String str = in.nextLine();  
  13.             System.out.println(str);  
  14.         }  
  15.   
  16.         URI uri = new URI("http://blog.csdn.net/xiazdong");  
  17.         System.out.println(uri.getScheme());  
  18.         System.out.println(uri.getSchemeSpecificPart());  
  19.         System.out.println(uri.getAuthority());  
  20.         System.out.println(uri.getUserInfo());  
  21.         System.out.println(uri.getHost());  
  22.         System.out.println(uri.getPort());  
  23.         System.out.println(uri.getPath());  
  24.         System.out.println(uri.getQuery());  
  25.         System.out.println(uri.getFragment());  
  26.   
  27.         String str = "/article/details/6705033";  
  28.         URI combined = uri.resolve(str);// 根据uri的路径把str变成绝对地址  
  29.         System.out.println(combined.getScheme()  
  30.                 + combined.getSchemeSpecificPart());  
  31.   
  32.         URI relative = uri.relativize(new URI(str));  
  33.         System.out.println(relative.getSchemeSpecificPart());  
  34.   
  35.     }  
  36.   
  37. }  


URL和URLConnection

URL的作用

1.如果想要获取某个网页的html源代码,比如http://blog.csdn.net/xiazdong 则只需要:

(1)URL url = new URL("http://blog.csdn.net/xiazdong");

(2)Scanner in = new Scanner(url.openStream());

即可.

2.获取消息头信息

  • URLConnection connection = url.openConnection();
  • connection.getHeaderFields()返回一个Map<String,List<String>>
  • connection.getContentLength();
  • connection.getContentType();
  • connection.setDoOutput(true)获得输出流
  • connection.getOutputStream();
  • connection.getInputStream();

代码示例:

[java] view plaincopy
  1. package org.core;  
  2.   
  3. import java.net.*;  
  4. import sun.misc.*;  
  5. import java.util.*;  
  6. import java.io.*;  
  7.   
  8. public class URLConnectionTest {  
  9.   
  10.     public static void main(String[] args) throws Exception {  
  11.         String urlName = "http://java.sun.com";  
  12.         URL url = new URL(urlName);  
  13.         URLConnection connection = url.openConnection();  
  14.         Map<String, List<String>> map = connection.getHeaderFields();  
  15.         for (Map.Entry<String, List<String>> entry : map.entrySet()) {  
  16.             String key = entry.getKey();  
  17.             List<String> value = entry.getValue();  
  18.             System.out.println(key + ":" + value);  
  19.         }     
  20.   
  21.     }  
  22.   
  23. }  



在网页中如果要提交数据给web服务器,通常要把数据发送给web服务器,然后web服务器委派一个脚本对数据进行处理,返回一个相应。

通常发送数据的方法有两种:get和post。

(1)get方法是直接把数据跟在url的后面,以name=value进行传输,

每个数据之间用&进行分割,value中的空格用+替换,非字母数字用%替换,并后跟两个16进制数,这种编码方式称为URL编码。URLEncoder和URLDecoder

(2)post方法是通过URLConnection发送给服务器,编码方式和get一样。URLEncoder.encode(VALUE,"UTF-8");

一般在传输中文时会运用编码和解码。

示例:通过URLEncoder和URLDecoder编码和解码


InetAddress  根据域名得到IP地址或名称

没有构造方法,通过:

(1)InetAddress i1 = InetAddress.getByName(String)返回一个InetAddress实例。

(2)如果一个地址有多个ip地址,比如google,有3个ip地址,就调用InetAddress[] i2 = InetAddress.getAllByName(String);

InetAddress.getLocalhost()获得本机的InetAddress实例。

代码实例:

 

[java] view plaincopy
  1. package org.core;  
  2.   
  3. import java.net.InetAddress;  
  4.   
  5. public class InetAddressTest {  
  6.   
  7.     public static void main(String[] args) throws Exception{  
  8.         InetAddress local = InetAddress.getLocalHost();  
  9.         System.out.println("本机地址:"+local.getHostAddress());  
  10.         System.out.println("本机名称:"+local.getHostName());  
  11.         InetAddress[] remote = InetAddress.getAllByName("www.google.com");  
  12.         for(InetAddress a : remote)  
  13.         {  
  14.             System.out.println("地址:"+a.getHostAddress());  
  15.             System.out.println("名称:"+a.getHostName());  
  16.         }     
  17.     }  
  18. }  


 

 

Socket(TCP)

Socket是一个用于机器之间通信的类。

Socket客户端:

(1)Socket s = new Socket(ip,port);打开一个套接字,发送请求    

(2)InputStream istream = s.getInputStream();接收数据

(3)OutputStream ostream  = s.getOutputStream();发送数据

需要用PrintWriter和Scanner进行包装,并且注意PrintWriter的自动缓冲。

Socket服务器:注意多个客户端同时访问服务器的问题:多线程

(1)ServerSocket server = new ServerSocket(port);创建一个端口

(2)Socket s = server.accept();        只有当有客户端请求并连接,函数才会返回

(3)InputStream istream = s.getInputStream();接收数据

(4)OutputStream ostream  = s.getOutputStream();发送数据

需要用PrintWriter和Scanner进行包装,并且注意PrintWriter的自动缓冲。

我们在使用PrintWriter时需要使用println()函数;


当服务器或客户端任意一方请求结束通信,则立刻停止。

问题1:在套接字中会发生阻塞的地方:

(1)实例化Socket时,会阻塞。

(2)在in.nextLine()类似操作时会阻塞。

解决方法:

(1)对于第一个问题,解决方法:

  • Socket s = new Socket();建立无连接socket
  • s.connect(new InetSocketAddress(host,port),timeout);设置超时。

(2)对于第二个问题,解决方法是设置s.setSoTimeout(long)设置超时时间

问题2:当客户端想要关闭套接字时,但却不能确定服务器是否还在发送数据,但是只要一关闭就立刻断开。

解决方法:

socket.shutdownOutput()关闭输出流

socket.shutdownInput()关闭输入流

半关闭示例代码:客户端发送hello给服务器,同时关闭输出流,服务器接收到后关闭输入流,等待5秒发送ECHO hello给客户端。

 Client:

[java] view plaincopy
  1. import java.net.*;  
  2. import java.io.*;  
  3. import java.util.*;  
  4. public class shutdownOutputClient {  
  5.   
  6.     public static void main(String[] args)throws Exception {  
  7.         Socket s = new Socket("localhost",8819);  
  8.         Scanner in = new Scanner(s.getInputStream());  
  9.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  10.         out.println("Hello");//输出hello  
  11.         s.shutdownOutput(); //关闭输出流  
  12.         System.out.println("关闭连接");  
  13.         while(in.hasNextLine()){  
  14.             System.out.println(in.nextLine());  
  15.         }  
  16.         s.close();  
  17.     }  
  18.   
  19. }  

Server:

[java] view plaincopy
  1. import java.net.*;  
  2. import java.io.*;  
  3. import java.util.*;  
  4. public class shutdownOutputServer {  
  5.   
  6.     public static void main(String[] args)throws Exception {  
  7.         ServerSocket server = new ServerSocket(8819);  
  8.         Socket s = server.accept();  
  9.         Scanner in = new Scanner(s.getInputStream());  
  10.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  11.         String str = in.nextLine();  
  12.         System.out.println(str);  
  13.         s.shutdownInput();  
  14.         System.out.println("关闭输入流");  
  15.           
  16.         Thread.sleep(5000);  
  17.         out.println("Echo:"+str);  
  18.         s.close();  
  19.     }  
  20.   
  21. }  


综合代码举例:实现一个简单的对等通信程序,通过多线程,一个线程接收数据,一个线程发送数据。

用户1:

[java] view plaincopy
  1. import java.util.*;  
  2. import java.io.*;  
  3. import java.net.*;  
  4. public class Client{  
  5.     public static void main(String[]args)throws Exception{  
  6.         Socket s = new Socket("localhost",8819);  
  7.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  8.         Thread t = new Thread(new Receive(s));  
  9.         t.start();  
  10.         //以下代码用于发送数据  
  11.         Scanner in = new Scanner(System.in);//键盘输入  
  12.         while(in.hasNextLine()){    //一直不断  
  13.             out.println(in.nextLine()); //发送键盘输入数据  
  14.         }  
  15.     }  
  16. }  
  17. class Receive implements Runnable   //这个类用于接收数据  
  18. {  
  19.     private Socket s;  
  20.     public Receive(Socket s)  
  21.     {  
  22.         this.s = s;  
  23.     }  
  24.     public void run()  
  25.     {  
  26.         try{  
  27.             Scanner in = new Scanner(s.getInputStream());   //in:接收数据  
  28.           
  29.             String str = null;  
  30.             while(true)  
  31.             {  
  32.                 str = in.nextLine();      
  33.                 System.out.println("服务器说:"+str);    //打印接收数据  
  34.             }  
  35.               
  36.         }  
  37.         catch(Exception e){}  
  38.     }  
  39. }  

用户2:

[java] view plaincopy<div styl
0 0
原创粉丝点击