Java网络编程 探险

我们先来看看计算机网络主要功能:资源共享;信息传输和集中处理;负载均衡和分布处理;综合信息服务。

实际上Java的网络编程就是服务器通过ServerSocket建立监听,客户端通过Socket连接到指定服务器后,通信双方就可以通过IO流进行通信了。

1.认识网络编程

计算机网络中实现通信的约定被称为通信协议,通信协议负责对传输速率、传输代码、代码结构、传输控制步骤、出错控制等制定处理标准。

计算机网络的OSI模型(各种计算机网络的参考标准)如下:

1)上层协议

http,ftp,https

2)底层协议

TCP/IP

IP(Internet Protocol,互联网协议):支持网间互联的数据报协议。

TCP(Transmission Control Protocol,传输控制协议):安全度更高,一般没有数据丢失。

UDP:效率更快,安全性相对低,可能会有数据丢失。

拓展: HTTP头:只是在TCP协议里面附带的一段内容。

通信协议组成:语义部分、语法部分、变换规则。

总结:所谓的协议就是在数据传输基础上封装自己的文本内容。

3)Java里的TCP/IP实现——Socket

Socket实现了TCP/IP,TCP/IP只是一份文档,各个不同的语言根据自己的需求对这个协议进行不同的解析,而在JAVA里对TCP/IP的解析实现就是Socket。

4)IP地址和端口号

IP地址:32位整数(4个8位二进制数),NIC统一负责全球IP地址的规划、管理,而Intel NIC、APNIC、RIPE三大网络信息中心具体负责美国及其他地区的IP地址分配,APNIC(总部在日本东京大学)负责亚太地区的IP管理,我国申请IP地址也要通过APNIC。

IP地址被分为A、B、C、D、E五类:

A类:10.0.0.0-10.255.255.255

B类:172.16.0.0-172.31.255.255

C类:192.168.0.0-192.168.255.255

端口号:16位整数,0-65535

公认端口:0-1023

注册端口:1024-49151

动态和私有端口:49152-65535

2.Java的网络支持

java.net包下URL和URLConnection等类提供了以编程方式访问web服务的功能,URLDecoder和URLEncoder提供了普通字符串和application/x-www-form-urlencoded MIME字符串相互转换的静态方法。

1)InetAddress

Java提供了InetAddress类表示IP地址

public class InetAddressTest {

	public static void main(String[] args) throws Exception {

		InetAddress ip = InetAddress.getByName("www.baidu.com"); // 根据主机名来获取对应的InetAddress实例
		System.out.println("baidu是否可达:" + ip.isReachable(2000)); // 判断是否可达
		System.out.println(ip.getHostAddress()); // 获取该InetAddress实例的IP字符串

		InetAddress local = InetAddress.getByAddress(new byte[]{127,0,0,1}); // 根据原始IP地址来获取对应的InetAddress实例
		System.out.println("本机是否可达:" + local.isReachable(5000));
		System.out.println(local.getCanonicalHostName()); // 获取该InetAddress实例对应的全限定域名
	}
}

2)URLDecoder和URLEncoder

用于普通字符串和application/x-www-form-urlencoded MIME字符串之间的相互转换

public class URLDecoderTest {

	public static void main(String[] args) throws Exception {
		// 将application/x-www-form-urlencoded字符串转换成普通字符串
		String keyWord = URLDecoder.decode("CSDN%E5%8D%9A%E5%AE%A2", "utf-8");
		System.out.println(keyWord);
		// 将普通字符串转换成application/x-www-form-urlencoded字符串
		String urlStr = URLEncoder.encode("CSDN博客" , "utf-8");
		System.out.println(urlStr);
	}
	/**
	 * 运行结果:
	 * CSDN博客
	 * CSDN%B2%A9%BF%CD
	 */
}

3)URL、URLConnection和URLPermission

URL:统一资源定位符,包含一个可打开到达该资源的输入流。

Java中还提供了URI:统一资源标识符,不能用于定位任何资源,只能解析,URL是URI的特例。

URLConnection:应用程序与URL之间的通信连接

HttpURLConnection:URL与URL之间的HTTP连接

程序可以通过URLConnection实例向URL发送请求、读取URL引用的资源。

如果既要使用输入流读取URLConnection响应的内容,又要使用输出流发送请求参数,则一定要先使用输出流,再使用输入流。

URL url = new URL(path); // // path:定义下载资源的路径
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000); // 设置超时时间
conn.setRequestMethod("GET"); // 设置请求方法
//设置通讯的头部信息,设置访问方式等
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.connect(); // 建立实际的连接

下面程序示范了向Web站点发送GET请求、POST请求,并从Web站点取得响应:

public class GetPostTest {

	/**
	 * 测试发送GET请求和POST请求
	 * @param args
	 */
	public static void main(String args[]) {
		// 发送GET请求
		String s = GetPostTest.sendGet("http://localhost:8888/GetPostServer/test.jsp", null);
		System.out.println(s);
		// 发送POST请求
		String s1 = GetPostTest.sendPost("http://localhost:8888/GetPostServer/login.jsp", "name=zhangsan&pass=123");
		System.out.println(s1);
	}

	/**
	 * 向指定URL发送GET方法的请求
	 * @param url 发送请求的URL
	 * @param param 请求参数,格式满足name1=value1&name2=value2的形式
	 * @return URL所代表远程资源的响应
	 */
	public static String sendGet(String url , String param) {
		String result = "";
		String urlName = url + "?" + param;
		try {
			URL realUrl = new URL(urlName);
			URLConnection conn = realUrl.openConnection(); // 打开和URL之间的连接
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; 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(
				// 定义BufferedReader输入流来读取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 发送请求的URL
	 * @param param 请求参数,格式应该满足name1=value1&name2=value2的形式
	 * @return URL所代表远程资源的响应
	 */
	public static String sendPost(String url , String param) {
		String result = "";
		try {
			URL realUrl = new URL(url);
			URLConnection conn = realUrl.openConnection(); // 打开和URL之间的连接
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");

			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);

			try(
				// 获取URLConnection对象对应的输出流
				PrintWriter out = new PrintWriter(conn.getOutputStream()))
			{
				// 发送请求参数
				out.print(param);
				// flush输出流的缓冲
				out.flush();
			}
			try(
				// 定义BufferedReader输入流来读取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("发送POST请求出现异常!" + e);
			e.printStackTrace();
		}
		return result;
	}

}

Web站点如下:

test.jsp:

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<!DOCTYPE>
<html>
<head>
	<title> 测试页面 </title>
	<meta name="website" content="http://www.crazyit.org"/>
</head>
<body>
	服务器时间为:<%=new java.util.Date()%>
</body>
</html>

login.jsp:

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String pass = request.getParameter("pass");
if(name.equals("zhangsan")&& pass.equals("123")) {
	out.println("登录成功!");
} else {
	out.println("登录失败!");
}
%>

3.基于TCP协议的网络编程

TCP/IP协议是一种可靠协议,它在通信两端各建立一个Socket,从而在通信两端之间形成网络虚拟链路进行通信,Java使用Socket对象来代表两端的通信接口,并通过Socket产生IO流来进行网络通信。

1)使用ServerSocket创建TCP服务端

// 创建一个ServerSocket,监听客户端Socket的连接请求
ServerSocket socket = new ServerSocket(10000); // 端口号推荐使用1024以上
// 采用循环不断的接受来自客户端的请求
while(true){
	Socket s = socket.accept();
	// 下面就能使用Socket进行通信了
	...
}

注意:每个TCP连接有两个Socket,当ServerSocket使用完毕后应使用ServerSocket的close()方法关闭该ServerSocket。

2)使用Socket进行通信

客户端可以使用Socket的构造方法了连接到指定服务器

Socket提供了如下两个方法来获取输入流和输出流:

InputStream getInputStream():返回该Socket对象对应的输入流

OutputStream getOutputStream():返回该Socket对象对应的输出流

Socket其他常用方法:

设置超时时长:setSoTimeout(int timeout)

为Socket连接服务器指定时长,Socket构造方法里没有提供指定时长的参数,所以需要使用下面代码进行操作:

// 创建一个无连接的Socket
Socket socket = new Socket();
// 让该Socket连接到远程服务器,如果经过10秒还没有连接上,则认为连接超时
socket.connect(new InetAddress(host, port), 10000);

下面以最简单的网络通信为例说明基于TCP协议的网络通信。

服务器端:

public class Server {

	public static void main(String[] args) throws IOException {

		ServerSocket socket = new ServerSocket(10000);
		while (true) {
			Socket s = socket.accept();
			PrintStream ps = new PrintStream(s.getOutputStream()); // 将Socket对应的输出流包装成PrintStream

			ps.println("您收到了服务器的消息!"); // 进行普通IO操作

			ps.close();
			s.close();
		}
	}
}

客户端:

public class Client {

	public static void main(String[] args) throws IOException {

		Socket socket = new Socket("127.0.0.1" , 10000);
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

		String line = br.readLine(); // 进行普通IO操作
		System.out.println("来自服务器的数据:" + line);

		br.close();
		socket.close();
	}
}

4.基于UDP协议的网络编程

1)使用DatagramSocket发送、接受数据

UDP(User Datagram Protocol,用户数据报协议):不可靠网络协议,面向非连接,通信效率较高。

UDP在通信两端各建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送、接受数据的对象。

Java提供了DatagramSocket(本身只是码头,不维护状态,不能产生IO流,唯一作用就是接受和发送数据报)作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接受的数据报。

DatagramSocket发送和接受的数据都是通过DatagramPacket对象完成的。

UDP和TCP对比如下:

TCP:可靠,传输大小无限制,需要建立连接,差错控制开销大。

UDP:不可靠,传输大小限制在64KB以下,不需要建立连接,差错控制开销小。

接受数据:

DatagramSocket socket = new DatagramSocket(port); // port:端口号

DatagramPacket packet = new DatagramPacket(buf, length);
socket.receive(packet); // 从DatagramPacket中接受数据报

发送数据:

DatagramSocket socket = new DatagramSocket(port); // port:端口号

DatagramPacket packet = new DatagramPacket(buf, length, address, port);
socket.send(packet); // 以DatagramPacket对象向外发送数据报

2)使用MulticastSocket实现多点广播

DatagramSocket只允许数据报发送到指定的目标地址,而MulticastSocket可以将数据报以广播方式发送到多个客户端。

MulticastSocket继承于DatagramSocket

多点广播示意图如下:

创建MulticastSocket对象后还需要加入到指定的多点广播地址,MulticastSocket使用joinGroup(InetAddress multicastAddr)方法加入到指定组,使用leaveGroup(InetAddress
multicastAddr)方法脱离一个组。

MulticastSocket用于发送、接受数据报的方法和DatagramSocket完全一样。但MulticastSocket多了一个setTimeToLive(int ttl)方法,ttl参数用于设置数据报最多可以跨过多少个网络(0:停留在本地主机;1:本地局域网;32:只能发送到本站点的网络上;64:保留在本地区;128:保留在本大洲;255:所有地方),默认1。

5.代理服务器

从Java5开始,java.net包下提供了Proxy(表示代理服务器)、ProxySelector(表示代理选择器)两个类

时间: 2024-10-10 18:11:59

Java网络编程 探险的相关文章

用java网络编程中的TCP方式上传文本文件及出现的小问题

自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文件给服务端,服务端接收数据并显示“上传成功”给客户端. 客户端: 1 import java.io.BufferedReader; 2 import java.io.FileReader; 3 import java.io.IOException; 4 import java.io.InputStr

Java网络编程基础(六)— 基于TCP的NIO简单聊天系统

在Java网络编程基础(四)中提到了基于Socket的TCP/IP简单聊天系统实现了一个多客户端之间护法消息的简单聊天系统.其服务端采用了多线程来处理多个客户端的消息发送,并转发给目的用户.但是由于它是基于Socket的,因此是阻塞的. 本节我们将通过SocketChannel和ServerSocketChannel来实现同样的功能. 1.客户端输入消息的格式 username:msg    username表示要发送的的用户名,msg为发送内容,以冒号分割 2.实现思路 实现思路与Java网络

java网络编程serversocket

转载:http://www.blogjava.net/landon/archive/2013/07/24/401911.html Java网络编程精解笔记3:ServerSocket详解ServerSocket用法详解 1.C/S模式中,Server需要创建特定端口的ServerSocket.->其负责接收client连接请求. 2.线程池->包括一个工作队列和若干工作线程->工作线程不断的从工作队列中取出任务并执行.-->java.util.concurrent->线程池

20145311实验四 &quot;Java网络编程及安全&quot;

20145311实验四 "Java网络编程及安全" 程序设计过程 实验内容 ·掌握Socket程序的编写:·掌握密码技术的使用:·设计安全传输系统 ·利用加解密代码包,编译运行代码,一人加密,一人解密:·集成代码,一人加密后通过TCP发送: 实验步骤 在这之前进行了一个socket连接的例子:用百度做了个实验 下面是两人合作进行RSA的加密: 首先建立一个Socket对象,用来连接特定服务器的指定端口(我负责的是服务器端,郑凯杰负责的是客户端,所以也就是输入我这边的ip地址),输入的参

java网络编程socket解析

转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在C/S通信模式中,client需要主动创建于server连接的Socket(套接字).服务器端收到了客户端的连接请求,也会创建与客户连接的Socket.Socket可看做是通信两端的收发器.server与client都通过Socket来收发数据. 1.构造Socket 1.Socket() 2.So

20145331实验五 Java网络编程及安全

实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统 4.结队伙伴:20145333赵嘉鑫 博客地址:http://home.cnblogs.com/u/5301z/ 5.分工:自己负责服务端,伙伴负责客户端 实验要求 1.基于Java Socket实现安全传输 2.基于TCP实现客户端和服务器,结对编程一人负责客户端,一人负责服务器 3.使用Git进行版本控制 4.选择对称算法进行数据加解密. 5.选择非对称算法对对称加密密

20145301实验五 Java网络编程及安全

北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.05.06 18:30-21:30 实验名称:实验五 Java网络编程 实验内容 1.用书上的TCP代码,实现服务器与客户端. 2.客户端与服务器连接 3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务器的公钥加密,计算明文的Hash函数值,一起传送给客户端 4.客户端用RSA公钥密码中服务器的私钥解密DES的,秘钥,用秘钥对密文进行解密,得出明文.计算

实验五 Java网络编程及安全

北京电子科技学院 实      验      报      告 课程:移动平台应用开发实践  班级:201592   姓名:曾俊宏  学号:20159210 成绩:___________  指导老师:娄嘉鹏    实验日期 :2015.10.25 实验名称:                          Java 网络编程及安全 实验内容:      1.掌握 Socket程序的编写    2.掌握密码技术的使用    3.设计安全传输系统 我的实验搭档是蔡斌思    http://www.

java网络编程socket\server\TCP笔记(转)

java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04|  分类: Socket |  标签:java  |举报|字号 订阅 1 TCP的开销 a  连接协商三次握手,c->syn->s,s->syn ack->c, c->ack->s b  关闭协商四次握手,c->fin->s, s->ack-c,s->fin->c,c->ack->s c  保持数据有序,响应确认等计算开销 d