java.net.Socket

  1. java.net.ServerSocket详解:https://blog.csdn.net/u012643122/article/details/47269205
  2. InputStream 、 InputStreamReader 、 BufferedReader区别:https://blog.csdn.net/lykangjia/article/details/70159619

java.net.Socket 是什么

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket。
任何一个Socket都是由IP地址和端口号唯一确定的。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
java.net.Socket_第1张图片
Socket也称为套接字,可以用来实现不同虚拟机或不同计算机之间的通信。在Java语言中,Socket可以分为两种类型:
(1)面向连接的Socket通信协议(TCP,传输控制协议)
(2)面向无连接的Socket通信协议(UDP,用户数据报协议)

基于TCP的通信过程如下

首先,Server端Listen指定的某个端口是否有连接请求(建议端口号大于1024);
其次,Client端向Server端发出Connect请求;
最后,Server端向Client端发回Accept消息。

一个连接就建立起来了,会话随即产生。
Server端和Client端都可以通过Send、Writer等方法与对方通信。

java.net.Socket的生命周期

Socket的生命周期分为3个阶段:
打开Socket、使用Socket收发数据、关闭Socket。

在java语言中,可以使用java.net.ServerSocket来作为服务器端,java.net.Socket作为客户端来实现网络通信。

java.net.ServerSocket重要属性

(1)port(服务器的端口号)
(2)backlog(最大客户端等待队列数,可选填)
用于ServerSocket,配置ServerSocket的最大客户端等待队列。等待队列的意思。
下面这个服务器最多可以同时连接3个客户端,其中2个等待队列:
int backlog = 2;
ServerSocket serverSocket = new ServerSocket(port, backlog);
这个参数设置为-1表示无限制,默认是50个最大等待队列,如果设置无限制,那么你要小心了,如果你服务器无法处理那么多连接,那么当很多客户端连到你的服务器时,每一个TCP连接都会占用服务器的内存,最后会让服务器崩溃的。

InputStream与InputStreamReader的区别

InputStream 是字节输入流的所有类的超类。
InputStreamReader 是字节流通向字符流的桥梁,它将字节流转换为字符流,通俗的说,就是一个流格式转换器。

java.io.BufferedWriter与java.io.PrintWriter.println(String s)的区别

PrintWriter和BufferedWriter都是继承java.io.Writer,所以很多功能都一样。
不过PrintWriter提供println()方法可以写不同平台的换行符,即自动换行,而BufferedWriter可以任意设定缓冲大小,但不能自动换行,需手动。
OutputStream可以直接传给PrintWriter(BufferedWriter不能接收),如:

PrintWriter pw
   = new PrintWriter(new BufferedOutputStream(new FileOutputStream("foo.out")));

或者用OutputStreamWriter来将OutputStream转化为Wrtier.这时就可以用BufferedWriter了。

java.net.BindException:Address already in use异常

这是端口被占用的结果,那么我们需要修改一下端口。

示例:要求客户端发送数据后能够回显相同的数据。

//首先,创建一个名为Server.java的服务器端代码
import java.io.*;
import java.net.*;

public class Server {
    public static void main(String[] arg){
        BufferedReader br =null;
        PrintWriter pw = null;
        try{
            ServerSocket serverSocket = new ServerSocket(99);
            Socket socket  = serverSocket.accept();
            //获取输入流
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //获取输出流
            pw = new PrintWriter(socket.getOutputStream(),true);
            //获取接收的信息
            String str = br.readLine();
            //发送相同的数据给客户端
            pw.println(str);
        }catch(Exception e){
            e.printStackTrace();            
        }finally{
            try{
                br.close();
                pw.close();
            }catch(Exception e){
                //e.printStackTrace();
            }
        }
    }
}
//其次,创建一个Client.java的客户端程序
import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] arg){
        BufferedReader br = null;
        PrintWriter pw = null;
        try{
            Socket socket = new Socket("localhost", 99);
            //获取输入流与输出流
            br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"gbk"));//InputStreamReader第二个参数可选填,默认为GBK
            pw = new PrintWriter(socket.getOutputStream(),true);
            //向服务器发送数据
            pw.println("你好!");
            //接收服务器发回的消息
            String str = null;
            while(true){//如果接收到的消息为空(没有接收到消息),则继续此循环
                str = br.readLine();
                if(str!=null)
                    break; //如果接收到的消息不为空(接收到了消息),则跳出此循环
            }
            System.out.println(str);
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try {
                br.close();
                pw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

最后启动Server,再启动Client。

NIO(Nonblocking IO)

OIO是读写阻塞,NIO是读写非阻塞。就是说服务器等待客户端连接这块都是阻塞的,一旦建立连接了,
OIO下,我读取客户端发来的信息会因为网络延时问题又一次阻塞,你发消息也是一样;
而NIO下,我的Selector.select()如果注册(添加)了【IO事件(connect、read或者write等)】,
当客户端消息到达服务器端时,【IO事件】从阻塞中醒来提醒我【“消息已经到达服务器,可以进行读写操作了”】,
换句话说,不是说阻塞消失了,而是我想多处阻塞等待还是一处阻塞,然后我干别的事,等数据到了再通知我处理。

NIO非阻塞的实现主要采用了Reactor(反应器)设计模式,这个模式与Observer模式类似,只不过Observer模式只能处理一个事件源,而Reactor模式可以处理多个事件源。

NIO通过Selector、Channel和Buffer来实现非阻塞的IO操作。
java.net.Socket_第2张图片

你可能感兴趣的:(java)