[疯狂Java讲义精粹] 第十二章|网络编程

1. 网络编程基础知识

1.1 网络基础知识
0. 网络分类:
  1. 按规模大小和延伸范围分: 局域网(LAN), 城域网(MAN), 广域网(WAN). 
  2. 按网络的拓扑结构分: 星型网络, 总线网络, 环线网络, 树型网络, 星型环线网络等. 
  3. 按传输介质: 双绞线网, 同轴电缆网, 光纤网, 卫星网等. 

1. 计算机网络中实现通信必须有一些约定, 这些约定被称为通信协议. 通信协议负责对传输速率, 传输代码, 代码结构, 传输控制步骤, 出错控制等制定处理标准. 

2. 通信协议由三部分组成: 
  1. 语义部分: 用于决定双方对话的类型. 
  2. 语法部分: 决定双方对话的格式. 
  3. 变换规则: 决定应答关系. 

3. OSI七层模型:
  1. Open System Interconnection, OSI, 开放系统互联参考模型. 
  2. OSI把网络分成七层: 物理层, 数据链路层, 网络层, 传输层, 会话层, 表示层, 应用层. 
  3. TCP协议(Transmission Control Protocol), 传输控制协议, 它规定一中可靠地数据信息传递服务. IP协议(Internet Protocol), 互联网协议, 是支持网间互联的数据报协议. 
1.2 IP地址和端口号
0. IP地址是一个32位(32bit)的整数, 端口是16位的整数. 

1. 端口用于表示数据交给哪个通信程序处理, 所以端口就是应用程序与外界交流的出入口. 

2. Java的基本网络支持

Java为网络支持提供了java.net包, 该包下的URL和URLConnection等类提供了一编程方式访问Web服务的功能, 而URLDecoder和URLEncoder提供了普通字符串和application/x-www-form-urlencoded MIME字符串互相转换的静态方法. 
2.1 使用InetAddress
0. Java使用InetAddress类代表IP地址, 有Inet4Address, Inet6Address两个子类. 

1. InetAddress没有构造器, 而有两个静态方法获取InetAddress实例: 
  1. getByName(String host): 根据主机获取对应的InetAddress对象. 
  2. getByAddress(byte[] addr): 根据原始IP地址获取对应的InetAddress对象. 

2. 三个方法获取InetAddress实例对应的IP地址和主机名:
  1. String getCanonicalHostName(): 获取此IP地址的全限定域名. 
  2. String getHostAddress(): 返回该InetAddress实例对应的IP地址字符串(以字符串形式). 
  3. String getHostName()
2.2 使用URLDecoder和URLEncoder
当URL地址里包含非西欧字符的字符串时, 系统会将这些字符串转换成applicatio/x-www-form-urlencoded MIME字符串. 这类过程使用这两个类:
  1. URLDecoder类包含一个decode(String s, String enc)静态方法, 将看上去乱码的特殊字符串转成普通字符串.  s是要操作的字符串, enc是编码方式(如"GBK"). 
  2. URLEncoder类包含一个encode(String s, String enc)静态方法, 把普通字符串转成applicatio/x-www-form-urlencoded MIME字符串. 
2.3 使用URL和URLConnection
0. URL(Uniform Resource Locator)对象代表统一资源定位器. 格式: protocol://host:port/resourceName . 

1. URL的方法: 
  1. String getFile(): 获得该URL的资源名. 
  2. String getHost(). 
  3. String getPath(). 
  4. int getPort(). 
  5. Strinig getProtocol(). 
  6. String getQuery(): 获取该URL的查询字符串部分. 
  7. URLConnection openConnection(): 返回一个URLConnection对象, 代表与URL所引用的远程对象的连接. 
  8. InputStream openStream(): 打开于此URL的连接, 并返回一个用于读取该URL资源的InputStream. 

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

TCP/IP通信协议在通信的两端各建一个Socket, 从而在通信的两端之间形成网络虚拟链路. Java使用Socket对象代表两端的通信端口, 并通过Socket产生IO流来进行网络通信. 
3.1 TCP协议基础
0. IP协议负责将信息从一个主机传送到另一个主机, 消息在传送的过程中被分割成一个个的小包. 

1. IP协议不能结局传输过程中可能出现的问题, 用TCP协议来提供可靠并且无差错的通信服务. 

2. 两台计算机连接时, TCP协议会让他们建立一个用于发送和接收数据的虚拟链路. TCP协议负责收集这些信息包, 并按次序传送, 接收端收到后再将它们正确还原. TCP保证数据包在传送中准确无误. TCP使用重发机制(发送信息后, 需要受到另一个通信实体的确认信息, 没有收到则重发.). 
3.2 使用ServerSocket创建TCP服务器端
0. Java中能接受其他通信实体连接请求的类是ServerSocket, ServerSocket对象用于监听来自客户端的Socket连接(如果没有连接, 将一直处于等待状态). 

1. ServerSocket的构造器: 
  1. ServerSocket(int port): 用指定端口port创建一个ServerSocket. 
  2. ServerSocket(int port, int backlog): 增加一个用来改变连接队列长度的参数backlog. 
  3. ServerSocket(int port, int backlog, InetAddress loaclAddr): 在及其存在多个IP地址的情况下, 允许通过localAddr参数指定将ServerSocket绑定到指定的IP地址. 

2. ServerSocket使用完毕后, 使用ServerSocket的close()方法关闭. 

3. ServerSocket包含一个监听来自客户端连接请求的方法: 
  • Socket accept(): 如果接收到一个客户端Socket的连接请求, 返回一个与客户端Socket对应的Socket; 否则该方法一直处于等待状态, 线程也被阻塞. 
3.3 使用Scocket进行通信
0. java.util.Socket的构造器: 
  1. Socket(InetAddress/String remoteAddress, int port): 创建连接到指定远程主机, 远程端口的Socket, 没有指定本地地址和端口, 默认使用本地主机的默认IP地址和系统动态分配的端口. 
    示例: 
    Socket s = new Socket("127.0.0.1", 30000); 
    # 执行上面代码是, 改代码将会连接到指定服务器, 让服务器端的ServerSocket的accept()方法向下执行, 与是服务器端和客户端产生了一对互相连接的Socket. 
  2. Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort): 指定了本底地址和端口, 使用与本地主机有多个IP地址的情况. 

1. 客户端和服务器端产生对应的Socket后, 就可以通过各自Socket通信了. 

2. Socket的两个方法获取输入流和输出流: 
  1. InputStream getInputStream(): 返回该Socket对象对应的输入流, 让程序通过该输入流从Socket中取出数据. 
  2. OutputStream getOutputStream() 

3. 例子. 
Server端: 
import java.net.*;
import java.io.*;

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(" *you get a message from server*" );
			ps.close();
			s.close();
		}
	}
}
Client端: 
import java.net.*;
import java.io.*;

public class Client
{
	public static void main(String[] args)
			throws IOException
	{
		Socket socket = new Socket("127.0.0.1", 30000);
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		String line = br.readLine();
		System.out.println("#FROM SERVER: " + line);
		br.close();
		socket.close();
	}
}
3.4 加入多线程
0. 服务器端应为每个Socket连接启动一个线程. 

1. 客户端读取服务器端的数据的线程同样会被阻塞, 所以应该单独启动一个线程负责读取服务器端的数据. 
3.5 记录用户信息
* 3.4 和 3.5讲C/S结构聊天室怎么写. 
3.6 半关闭的Socket
0. 要表示输出已经结束可以通过关闭输出流来实现, 但是在网络通信中如果关闭输出流, 则对应的Socket也将随之关闭, 这样导致程序无法从该Socket的输入流中读取数据. 

1. Socket低通两个瓣关闭的方法, 只关闭Socket的输入流或者输出流, 用以表示输出数据已经发送完成: 
  1. shutdownInput(): 关闭该Socket的输入流, 程序还可以通过该Socket的输出流输出数据. 
  2. shutdownOutput(). 
如果一个Socket实例先后调用了shutdownInput()和shutdownOutput()方法, 此Socket也没关闭, 只是出于不能读写数据的状态了. 
3.7  使用NIO实现非阻塞Socket通信
# 使用NIO的多人聊天室. 
3.8 使用Java7的AIO实现非阻塞通信
Java 7的NIO.2提供了异步Channel支持, 基于异步Channel的IO机制叫异步IO(Asynchronous IO, AIO). 

# AIO聊天工具. 


----------------------------------------
挖坑不填
----------------------------------------
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值