前言
计算机网路实现了多个网络终端的互联,彼此之间能够进行数据交流。而网络应用程序就是在已连接的不同终端设备上运行的程序,这些网络程序相互之间可以进行数据交互。
网络程序的数据交互则依赖于TCP/IP协议,在实际应用中TCP网络程序提供可靠的数据通信,而UDP网络程序则不保证数据的可靠性,但是协议简单、传输速度快(比如用在音视频数据传输,它们不需要很高的可靠性,偶尔丢帧是可以忍受的)。
java.net包介绍
接口摘要
- ContentHandlerFactory ;此接口定义内容处理程序的工厂。
- CookiePolicy CookiePolicy 实现决定应该接受哪个 cookie 以及应该拒绝哪个 cookie。
- CookieStore ;表示 cookie 存储区的 CookieStore 对象。
- DatagramSocketImplFactory ;此接口定义用于数据报套接字实现的工厂。
- FileNameMap ;提供在文件名和 MIME 类型字符串之间进行映射的机制的简单接口。
- SocketImplFactory ;此接口定义用于套接字实现的工厂。
- SocketOptions ;获取/设置套接字选项的方法的接口。
- URLStreamHandlerFactory ;该接口为 URL 流协议处理程序定义一个工厂。
类摘要
- Authenticator Authenticator 类表示懂得如何获得网络连接验证的对象。
- CacheRequest ;表示在 ResponseCache 中存储资源的通道。
- CacheResponse ;表示从 ResponseCache 获取资源的通道。
- ContentHandler抽象类ContentHandler 是从 URLConnection 读取 Object 的所有类的超类。
- CookieHandler CookieHandler 对象提供一种回调机制以将 HTTP 状态管理策略实现挂钩到 HTTP 协议处理程序。
- CookieManager CookieManager 提供 CookieHandler 的具体实现,它将 cookie(辨别用户身份的本地终端数据) 的存储区与围绕接受和拒绝 cookie 的策略分离开来。
- DatagramPacket ;此类表示数据报包。
- DatagramSocket ;此类表示用来发送和接收数据报包的套接字。
- DatagramSocketImpl ;数据报和多播套接字实现的抽象基类。
- HttpCookie HttpCookie 对象表示一个 http cookie,该 cookie 带有服务器和用户代理之间的状态信息。
- HttpURLConnection;支持 HTTP 特定功能的 URLConnection。
- IDN ;提供在普通 Unicode 表示形式和 ASCⅡ 兼容性编码 (ACE) 表示形式之间进行国际化域名 (IDN) 转换的方法。
- Inet4Address ;此类表示 Internet Protocol version 4 (IPv4) 地址。
- Inet6Address ;此类表示互联网协议第 6 版 (IPv6) 地址。
- InetAddress ;此类表示互联网协议(IP) 地址。
- InetSocketAddress ;此类实现 IP套接字地址(IP 地址 +端口号)。
- InterfaceAddress ;此类表示网络接口地址。
- JarURLConnection ;连接到 Java ARchive (JAR) 文件或 JAR 文件中条目的 URL Connection。
- MulticastSocket多播数据报套接字类用于发送和接收 IP 多播包。
- NetPermission ;此类可用于各种网络权限。
- NetworkInterface ;此类表示一个由名称和分配给此接口的 IP 地址列表组成的网络接口。
- PasswordAuthentication PasswordAuthentication 类是供 Authenticator 使用的数据持有者。
- Proxy ;此类表示代理设置,通常为类型(http、socks)和套接字地址。
- ProxySelector ;连接到 URL 引用的网络资源时选择要使用的代理服务器(如果有)。
- ResponseCache ;表示 URLConnection 缓存的实现。
- SecureCacheResponse ;表示最初通过安全方法(如 TLS)获得的缓存响应。
- ServerSocket ;此类实现服务器套接字。
- Socket ;此类实现客户端套接字(也可以就叫“套接字”)。
- SocketAddress ;此类表示不带任何协议附件的 Socket Address。
- SocketImpl抽象类SocketImpl 是实际实现套接字的所有类的通用超类。
- SocketPermission ;此类表示通过套接字对网络的访问。
- URI ;表示一个统一资源标识符 (URI) 引用。
- URL ;类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。
- URLClassLoader ;该类加载器用于从指向 JAR 文件和目录的 URL 的搜索路径加载类和资源。
- URLConnection抽象类URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。
- URLDecoder HTML 格式解码的实用工具类。
- URLEncoder HTML 格式编码的实用工具类。
- URLStreamHandler抽象类URLStreamHandler 是所有流协议处理程序的通用超类。
枚举摘要
- Authenticator.RequestorType ;请求验证的实体的类型。
- Proxy.Type ;表示代理类型。
简单的示例
TCP编程示例
服务端
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class MyTcpServer { private BufferedReader reader; private PrintWriter writer; private ServerSocket serverSocket; private Socket socket; private BufferedReader sin; void getServer(){ try { serverSocket = new ServerSocket(8866); System.out.println("服务器套接字已经创建完成"); while (true){ System.out.println("等待客户机的连接"); socket = serverSocket.accept(); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); writer = new PrintWriter(socket.getOutputStream(), true); sin=new BufferedReader(new InputStreamReader(System.in)); getClientMessage(); } } catch (IOException e) { e.printStackTrace(); } } private void getClientMessage(){ String line ; try{ while(true){ System.out.println("客户端信息接收:"+ reader.readLine()); writer.println("欢迎您连接服务端"); line=sin.readLine(); while(!line.equals("bye")){ writer.println(line); writer.flush(); System.out.println("客户端信息接收:"+ reader.readLine()); line=sin.readLine(); } } }catch(Exception e){ e.printStackTrace(); } try{ if(reader != null){ reader.close(); } if(writer != null){ writer.close(); } if(socket != null){ socket.close(); } }catch(IOException e){ e.printStackTrace(); } } public static void main(String[] args) { MyTcpServer myTcpServer = new MyTcpServer(); myTcpServer.getServer(); } }
客户端
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class MyTcpClient { private PrintWriter writer; private BufferedReader reader; Socket socket; public void connect(){ System.out.println("尝试连接"); try { socket = new Socket("127.0.0.1", 8866); writer = new PrintWriter(socket.getOutputStream(),true); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println("连接成功"); writer.println("你好,来自客户端的连接"); getserverMessage(); } catch (IOException e) { e.printStackTrace(); } } private void getserverMessage(){ String line ; try{ while(true){ System.out.println("服务端信息接收:"+ reader.readLine()); BufferedReader sin=new BufferedReader(new InputStreamReader(System.in)); line=sin.readLine(); while(!line.equals("bye")){ writer.println(line); writer.flush(); System.out.println("服务端信息接收:"+ reader.readLine()); line=sin.readLine(); } } }catch(Exception e){ e.printStackTrace(); } try{ if(reader != null){ reader.close(); } if(writer != null){ writer.close(); } if(socket != null){ socket.close(); } }catch(IOException e){ e.printStackTrace(); } } public static void main(String[] args) { MyTcpClient tcpclient; tcpclient = new MyTcpClient(); tcpclient.connect(); } }
TCP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt(); * 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、开启监听,用函数listen();
5、接收客户端上来的连接,用函数accept();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
8、关闭监听;
TCP编程的客户端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置要连接的对方的IP地址和端口等属性;
5、连接服务器,用函数connect();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
UDP编程示例
客户端
import java.io.IOException; import java.io.InterruptedIOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPClient { private static final int TIMEOUT = 5000; //设置接收数据的超时时间 private static final int MAXNUM = 5; //设置重发数据的最多次数 public static void main(String args[]) throws IOException { String str_send = "Hello UDPserver"; byte[] buf = new byte[1024]; //客户端在9000端口监听接收到的数据 DatagramSocket ds = new DatagramSocket(9000); //获取本地IP InetAddress loc = InetAddress.getLocalHost(); //定义用来发送数据的DatagramPacket实例 DatagramPacket dp_send= new DatagramPacket(str_send.getBytes(),str_send.length(),loc,3000); //定义用来接收数据的DatagramPacket实例 DatagramPacket dp_receive = new DatagramPacket(buf, 1024); //数据发向本地3000端口 ds.setSoTimeout(TIMEOUT); //设置接收数据时阻塞的最长时间 int tries = 0; //重发数据的次数 boolean receivedResponse = false; //是否接收到数据的标志位 //直到接收到数据,或者重发次数达到预定值,则退出循环 while(!receivedResponse && tries<MAXNUM){ //发送数据 ds.send(dp_send); try{ //接收从服务端发送回来的数据 ds.receive(dp_receive); //如果接收到的数据不是来自目标地址,则抛出异常 if(!dp_receive.getAddress().equals(loc)){ throw new IOException("Received packet from an umknown source"); } //如果接收到数据。则将receivedResponse标志位改为true,从而退出循环 receivedResponse = true; }catch(InterruptedIOException e){ //如果接收数据时阻塞超时,重发并减少一次重发的次数 tries += 1; System.out.println("Time out," + (MAXNUM - tries) + " more tries..." ); } } if(receivedResponse){ //如果收到数据,则打印出来 System.out.println("client received data from server:"); String str_receive = new String(dp_receive.getData(),0,dp_receive.getLength()) + " from " + dp_receive.getAddress().getHostAddress() + ":" + dp_receive.getPort(); System.out.println(str_receive); //由于dp_receive在接收了数据之后,其内部消息长度值会变为实际接收的消息的字节数, //所以这里要将dp_receive的内部消息长度重新置为1024 dp_receive.setLength(1024); }else{ //如果重发MAXNUM次数据后,仍未获得服务器发送回来的数据,则打印如下信息 System.out.println("No response -- give up."); } ds.close(); } }
服务端
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UDPService { public static void main(String[] args)throws IOException { String str_send = "Hello UDPclient"; byte[] buf = new byte[1024]; //服务端在3000端口监听接收到的数据 DatagramSocket ds = new DatagramSocket(3000); //接收从客户端发送过来的数据 DatagramPacket dp_receive = new DatagramPacket(buf, 1024); System.out.println("server is on,waiting for client to send data......"); boolean f = true; while(f){ //服务器端接收来自客户端的数据 ds.receive(dp_receive); System.out.println("server received data from client:"); String str_receive = new String(dp_receive.getData(),0,dp_receive.getLength()) + " from " + dp_receive.getAddress().getHostAddress() + ":" + dp_receive.getPort(); System.out.println(str_receive); //数据发动到客户端的3000端口 DatagramPacket dp_send= new DatagramPacket(str_send.getBytes(),str_send.length(),dp_receive.getAddress(),9000); ds.send(dp_send); //由于dp_receive在接收了数据之后,其内部消息长度值会变为实际接收的消息的字节数, //所以这里要将dp_receive的内部消息长度重新置为1024 dp_receive.setLength(1024); } ds.close(); } }
UDP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、循环接收数据,用函数recvfrom();
5、关闭网络连接;
UDP编程的客户端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置对方的IP地址和端口等属性;
5、发送数据,用函数sendto();
6、关闭网络连接;
总结
Java提供了Socket和ServerSocket类,让我们可以实现TCP/UDP协议的连接;
Java还提供了MAIL API,我们可以实现基于SMTP/POP3协议的收发邮件功能;
最后Java还提供了HttpURLConnection类,用于实现HTTP客户端功能,以及提供了Servlet API用于实现HTTP服务端的编程。