文章目录
- 一、java网络编程
- 1、基础知识
- a、ip地址和端口号
- b、TCP和UDP协议
- c、URL
- d、InetAddress
- 1、基础知识
- 2、socket
- a、创建socket实例
- b、客户端连接
- 步骤:
- c、服务端连接
- 步骤:
- d、总结
- 二、阻塞IO
- 1、java的IO接口
- a、基于字节操作的IO接口
- b、基于字符操作的IO接口
- c、基于磁盘操作的IO接口
- d、基于网络操作的IO接口
- 2、阻塞IO的通信模型
- 3、总结
- a 、 BIO数据在写入OutputStream和从InputStream读取时,都有可能发生阻塞
- b 、当前一些需要大量http长连接的情况
- c 、需要另外一种新的IO操作方式
- 1、java的IO接口
- 三、NIO
- 1、工作原理
- 2、通信模型
- 3、实例
- 客户端代码:
- 服务端代码
一、java网络编程
1、基础知识
a、ip地址和端口号
b、TCP和UDP协议
c、URL
代码语言:javascript复制 public static void main(String[] args) throws IOException {
//使用URL读取网页内容
//1、创建一个URL实例
URL url = new URL("http://www.baidu.com");
InputStream inputStream = url.openStream();// 2、使用openStream()获取资源的字节输入流
//3、将字节流转换为字符流,如果不指定编码,中文可能会出现乱码
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
//4、为字符输入流添加缓存,提高读取效率
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String string = bufferedReader.readLine(); //5、读取数据
while(string != null) {
System.out.println(string); //输出数据
string = bufferedReader.readLine();
}
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
}
d、InetAddress
2、socket
a、创建socket实例
b、客户端连接
步骤:
1)、创建socket对象 2)、建立连接后,通过输出流向服务端发送请求信息 3)、通过输入流获取服务端返回的响应信息 4)、关闭响应资源
代码语言:javascript复制public static void main(String[] args) throws IOException {
//客户端
//1、创建socket对象
Socket socket = new Socket("localhost", 10086);
//2、获取输出流,向服务器发送信息
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);//将输出流包装成打印流
printWriter.write("用户名: admin; 密码:123");
printWriter.flush();
socket.shutdownOutput();
//3、获取输入流,并读取服务端的响应信息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String string = null;
while((string = bufferedReader.readLine()) != null){
System.out.println("我是客户端,服务端说:" string);
}
//4、关闭响应资源
bufferedReader.close();
inputStream.close();
printWriter.close();
outputStream.close();
socket.close();
}
c、服务端连接
步骤:
1)、创建ServerSocket对象, 绑定监听端口 2)、通过accept() 方法监听客户端请求 3)、连接建立后,通过输入流读取客户端发送的请求信息 4)、通过输出流向客户端发送信息 5)、关闭相关资源
代码语言:javascript复制public static void main(String[] args) throws IOException {
/**
*服务端,基于Tcp协议的socket通信,实现用户登录
*/
//1、创建serverSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(10086);
//2、调用accept()方法开始监听,等待客户端的连接
Socket socket = serverSocket.accept();
//3、获取输入流,并读取客户端信息
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String string = null;
while((string = bufferedReader.readLine()) != null){
System.out.println("我是服务端,客户端说:" string);
}
socket.shutdownInput(); //关闭输入流
//4、获取输出流,向客户端发送信息
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.write("欢迎您!");
printWriter.flush();
//5、关闭资源
printWriter.close();
outputStream.close();
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
socket.close();
serverSocket.close();
}
d、总结
1)、创建ServerSocket和Socket 2) 、打开连接到Socket的输入输出流 3)、按照协议对Socket进行读写操作 4)、关闭输入输出流、关闭socket
二、阻塞IO
1、java的IO接口
数据和传输方式是最影响效率的两个方面。
a、基于字节操作的IO接口
b、基于字符操作的IO接口
c、基于磁盘操作的IO接口
d、基于网络操作的IO接口
2、阻塞IO的通信模型
3、总结
a 、 BIO数据在写入OutputStream和从InputStream读取时,都有可能发生阻塞
b 、当前一些需要大量http长连接的情况
c 、需要另外一种新的IO操作方式
三、NIO
1、工作原理
(补充)
2、通信模型
(补充)
3、实例
客户端代码:
代码语言:javascript复制public class NIOClient {
//通道管理器
private Selector selector;
/**
*获取一个socket通道,并对该通道做一些初始化工作
*/
public void initClient(String ip, int port) throws IOException {
//获取一个socket通道
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false); //设置通道为非阻塞
//获取一个通道管理器
this.selector = Selector.open();
//客户端连接服务器,其实方法执行并没有实现连接,
// 需要在Listen()方法中调用channel.finishConnect()才能完成连接
socketChannel.connect(new InetSocketAddress(ip, port));
//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT
socketChannel.register(selector, SelectionKey.OP_CONNECT);
}
/**
*采用轮寻的方式监听selector上是否有需要处理的事件,如果有,则进行处理
*/
public void listen() throws IOException{
//轮寻访问selector
while (true){
selector.select();
//获取selector中选中的项的迭代器
Iterator iterator = this.selector.selectedKeys().iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = (SelectionKey)iterator.next();
//删除已选的key,以防重复处理
iterator.remove();
//连接事件发生
if(selectionKey.isAcceptable()){
SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
//如果正在连接,则完成连接
if(socketChannel.isConnectionPending()){
socketChannel.finishConnect();
}
//设置成非阻塞
socketChannel.configureBlocking(false);
//在这里可以给服务器发送消息
socketChannel.write(ByteBuffer.wrap(new String("向服务端发送了一条消息").getBytes()));
//在和服务端连接成功后,为了可以接收到服务端的消息,需要给通道设置读的权限
socketChannel.register(this.selector, SelectionKey.OP_READ);
}else if(selectionKey.isReadable()){//获取了可读的条件
read(selectionKey);
}
}
}
}
/**
* 处理读取服务端发送来的信息的事件
*/
public void read(SelectionKey selectionKey){
//和服务端的read方法一样
}
}
服务端代码
代码语言:javascript复制public class NIOServer {
//通道管理器
private Selector selector;
/**
*获取一个ServerSocket通道,并对该通道做一些初始化工作
*/
public void initServer(int port) throws IOException {
//获取一个ServerSocket通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置通道为非阻塞
serverSocketChannel.configureBlocking(false);
//将该通道对应的ServerSocket绑定到端口
serverSocketChannel.socket().bind(new InetSocketAddress(port));
//获得一个通道管理器
selector = Selector.open();
//将通道管理器和该通道进行绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,
// 当事件到达时,selector.select()会返回,如果该事件没到达,selector.select()会一直阻塞
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
/**
*采用轮寻的方式监听selector上是否有需要处理的事件,如果有,则进行处理
*/
public void listen() throws IOException{
System.out.println("服务器启动成功");
//轮寻访问selector
while(true){
//当注册的事件到达时,方法返回,否则,该方法一直阻塞
selector.select();
//获取selector中选中的项的迭代器,选中的项为注册的事件
Iterator iterator = this.selector.selectedKeys().iterator();
if(iterator.hasNext()){
SelectionKey selectionKey = (SelectionKey) iterator.next();
//删除已选的key,以防重复处理
iterator.remove();
//客户端请求连接事件
if(selectionKey.isAcceptable()){
ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
//获得和客户端连接的通道
SocketChannel socketChannel = serverSocketChannel.accept();
//设置成非阻塞
socketChannel.configureBlocking(false);
//在这里可以给客户端发送消息
socketChannel.write(ByteBuffer.wrap(new String("向客户端发送一条消息").getBytes()));
//在和客户端连接成功后,为了可以接收到客户端的信息,需要给通道设置读的权限
socketChannel.register(this.selector, SelectionKey.OP_READ);
}else if(selectionKey.isReadable()) { //获得了可以读的权限
read(selectionKey );
}
}
}
}
/**
* 处理读取客户端发送来的信息的事件
*/
public void read(SelectionKey selectionKey) throws IOException{
//服务端可以读取消息: 得到事件发生的socket通道
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
//创建读取的缓存区
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
socketChannel.read(byteBuffer);
byte[] data = byteBuffer.array();
String msg = new String(data).trim();
}
}