JAVASocket实现聊天室「建议收藏」

JAVASocket实现聊天室「建议收藏」JAVASocket实现聊天室文章目录JAVASocket实现聊天室Sokcet是什么JAVASOCKET编程中的两个重要对象ServerSocket构造方法acceptbindcloseSocket构造方法getInputStream,getOutputStreamclose聊天室实现服务端实现客户端实现读线程实现写线程实现运行结果Sokcet是什么socket本质上是两个端点之间的通…

大家好,又见面了,我是你们的朋友全栈君。

JAVASocket实现聊天室

在这里插入图片描述

Sokcet是什么

socket本质上是两个端点之间的通信桥梁,两个端点相互连接,并且打开远程之间的网络IO,从而可以像对本地文件读写一样,JAVA对socket编程有着友好的支持,并且针对客户端和服务端抽象了不同的服务对象

JAVA SOCKET编程中的两个重要对象

JDK对Socket编程抽象了两个类ServerSocketSocket,分别封装了客户端和服务端的基本通信API

ServerSocket

JDK提供的服务端实现,主要用于监听服务端口,并且接受来自该端口的客户端请求,并且生成来自客户端的Socket对象。

几个重要的方法:

构造方法

  • ServerSocket()
  • ServerSocket(int port)
  • ServerSocket(int port,int backlog)
  • ServerSocket(int port,int backlog,InnetAddress bindAddr)

上述构造方法设计到大致三个参数,port(端口),backlog请求客户端队列最大长度,bindAddr,将要绑定的IP实现,如果不指定默认本地IP。

accept

public Socket accept() throws IOException

accept方法主要是在开启端口监听之后接受一个客户端的连接请求,如果没有请求进来,那么accept方法会一直阻塞,直到一个客户端的请求进入,accept方法在接受一个客户端的请求之后,会生成一个客户端的Socket对象,这个对象封装了客户端的IO请求。

Socket client = serverSocket.accept();
//对客户端的输入输出流
OutputStream outputStream= client.getOutputStream();
InputStream  inputStream = client.getInputStream();

服务端可通过这个Socket对象获取对客户端的输入流和输出流,这样服务端就可以读取到客户端发送来的的消息,并且可以向客户端发送消息

bind

bind方法是真正实现socket套接字绑定IP和端口的实现,默认在ServerSocket的构造方法中会进行调用。

public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException { 
   
        ...
        try { 
   
            bind(new InetSocketAddress(bindAddr, port), backlog);
        } catch(SecurityException e) { 
   
            close();
            throw e;
        } catch(IOException e) { 
   
            close();
            throw e;
        }
}
       

close

当主动调用close方法后,服务器会释放当前绑定的端口,并且自动断开和所有客户端之间的连接,只有主动执行了ServerSocket的close()方法,isClosed()方法才返回true;否则,即使ServerSocket还没有和特定端口绑定,isClosed()方法也会返回false,这是因为服务端内部维护了一个closed变量,初始化为false,只有在调用了close方法才会将closed变量置为true

Socket

JDK提供的Socket套接字实现类,主要封装了端的IO操作,通过Socket对象我们可以实现对客户端及服务端的读写操作

构造方法

Socket(InetAddressaddress, int port);
Socket(InetAddress address,int port, boolean stream);
Socket(String host, intprot);
Socket(String host, intprot, boolean stream);
Socket(SocketImpl impl)
Socket(String host, intport, InetAddress localAddr, Socket(InetAddress address,int port, InetAddress localAddr, int localPort)
ServerSocket(int port);
ServerSocket(int port, intbacklog);
ServerSocket(int port, intbacklog, InetAddress bindAddr)

其中address、host和port分别是双向连接中另一方的IP地址、 主机名和端口号,stream指明socket是流socket还是数据报 socket,localPort表示本地主机的端口号,localAddr和bindAddr是本地机器的地址(ServerSocket的主机地 址),impl是socket的父类,既可以用来创建serverSocket又可以用来创建Socket。count则表示服务端所能支持的最大连接数。

Socket(String host, intprot)

常用的构造方法默认指定host和port,表示要建立的远程连接的服务端IP和端口,在服务端开启端口监听之后,客户端可以得到一个连接到服务端的Socket对象,同时服务端也会得到一个连接到客户端的Socket对象,这样双方可基于Socket实现双向通信,发送并且接受消息

getInputStream,getOutputStream

获取对应端的输入输出流,当双方建立连接后,双方互相持有封装了对方IO操作的Sokcet对象,通过Socket对象获取对应的输入输出流实现双向通信。

close

当客户端的Socket关闭连接时,服务端与客户端的连接自动关闭,但是服务端会继续监听端口,等待新的连接进来。

当服务端的Sokcet关闭连接时,服务端与所有客户端的连接将全部断开,并且释放对应监听接口

聊天室实现

服务端实现

监听端口,调用accept方法等待客户端请求,另外新起两个线程分别针对客户端的读写进行处理

public class Server { 
   

    public static final Integer port =80;

    public static void main(String[] args) throws IOException { 
   
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("服务端监听 "+port+" 端口成功!,等待客户端连接");
        while (true){ 
   
            Socket client = serverSocket.accept();
            System.out.println("一个新的客户端进来了");
            new WriteHelper(client.getOutputStream(),"连接客户端成功!,可以畅所欲言了").start();
            new PrintHelper(client.getInputStream(),"服务端").start();
        }
    }


}

客户端实现

绑定ip和端口,并且启动两个线程分别处理来自服务端的读写

public class Client { 
   

    public static void main(String[] args) throws IOException, InterruptedException { 
   
        Socket socket = new Socket("127.0.0.1", 80);
        new WriteHelper(socket.getOutputStream(),"连接服务端成功!,可以畅所欲言了").start();
        new PrintHelper(socket.getInputStream(),"客户端").start();
    }
}

针对Socket的输入输出流实现单独线程处理,读写不互相收影响

读线程实现

主要针对Sokcet对象的输入流进行单独处理

public class PrintHelper extends Thread{ 
   

    private InputStream inputStream;
    private String type;

    public PrintHelper(InputStream inputStream,String type) { 
   
        this.inputStream=inputStream;
        this.type=type;
    }

    public void run() { 
   
        byte[] bytes = new byte[1024];
        int length;
        try { 
   
            while (true){ 
   
                if (((length=inputStream.read(bytes))>1)){ 
   
                    String s = new String(bytes, 0, length);
                    LocalDateTime nowLocalDate = LocalDateTime.now();
                    String time = nowLocalDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    System.out.println(" "+time+" "+type+" : "+s);
                    System.out.println("____________________________________________");
                }
            }
        } catch (IOException e) { 
   
            e.printStackTrace();
        }
    }

}

写线程实现

主要针对Socket对象的输出流进行单独处理,

public class WriteHelper extends Thread{ 
   

        private OutputStream outputStream;

        public WriteHelper(OutputStream outputStream,String message) { 
   
            System.out.println(message);
            System.out.println("============================");
            this.outputStream=outputStream;
        }

        public void run() { 
   
            Scanner scanner = new Scanner(System.in);
            while(true){ 
   
                String next = scanner.next();
                try { 
   
                    outputStream.write(next.getBytes());
                    outputStream.flush();
                } catch (IOException e) { 
   
                    e.printStackTrace();
                }
            }
        }
}

运行结果

需要先启动服务端,开启端口监听,再启动客户端,实现IP加端口的连接

启动服务端

在这里插入图片描述

客户端连接

在这里插入图片描述

在这里插入图片描述

客户端发送消息

在这里插入图片描述

服务端收到消息

在这里插入图片描述

服务端回复消息

在这里插入图片描述

客户端收到消息

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148336.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SPSS操作(四):系统聚类分析

    SPSS操作(四):系统聚类分析现用如下数据做系统聚类分析:将数据导入spss中,如图:步骤如下:①【分析】—-【分类】—-【系统聚类】②x2、x3、x4、x5、x6、x7、x8添加到变量,x1(即地区)添加到个案标注依据小技巧:添加变量的时候,可以单击【医疗机构床位数(张)】,然后按住shift键不松,鼠标单击【医院(个)】就可以选择多个变量一起添加③点击【统计】勾选【解的范围】,可以根据自己的需要选择最小聚类数和最大聚类数(这里我设置为2和5),然后点击【继续】④点击【图】,(这里我选择的是做系谱图

    2022年10月18日
    6
  • linux下luajit安装

    linux下luajit安装#cd /usr/local/#wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz#tar zxvf LuaJIT-2.0.4.tar.gz编辑src/Makefile,注释DLUAJIT_ENABLE_LUA52COMPAT所在的行#make & make install

    2022年10月7日
    5
  • 无刷直流电机模糊PID控制「建议收藏」

    无刷直流电机在克服了有刷直流电机机械换相缺点的同时,又具有结构简单、运行可靠以及调速性能好等优点,在很多领域中得到了广泛的应用。本次课题阐述了无刷直流电机的基本结构、运行原理和数学模型,并以无刷直流电机为被控对象,根据电机的特点和控制要求确定了三闭环控制策略,分别是位置、转速及电流环控制三者之间实行串级连接。采用模糊PID控制理论,搭建无刷直流电机和控制器的仿真模型来验证电机控制策略的可行性,使要能使伺服控制器的具体性能满足:无静差,响应快,超调量小的设计要求。结合三闭环控制结构的特点,在位置环中采用模

    2022年4月16日
    69
  • xampp环境配置下出现的问题解决 — mysqli_real_connect(): (HY000/1045): Access denied for user ‘root‘@‘localhost‘

    xampp环境配置下出现的问题解决 — mysqli_real_connect(): (HY000/1045): Access denied for user ‘root‘@‘localhost‘XAMPP环境配置下出现的问题版本:xampp7.3.1    今天,柳妹在虚拟机上面又一次搭建xampp的环境的时候,在mysql的管理界面对于root@localhost管理用户进行密码设定的时候,修改了密码,当再一次点击进入的时候,报错如下:MySQL返回:无法连接:无效的设置。mysqli_real_connect():(HY000/1045):Accessde…

    2022年7月12日
    22
  • 零是奇数还是偶数?

    零是奇数还是偶数?

    2021年10月17日
    141
  • python读取excel文件代码_python怎么加速读取excel

    python读取excel文件代码_python怎么加速读取excel1.excel文件只包含一个sheet表importxlrd”””读取包含耽搁sheet的excel数据”””workbook=xlrd.open_workbook(“test.xlsx”)#打开工作表sheet0=workbook.sheet_by_index(0)#获取工作簿nrows=sheet0.nrows#获取总行数foriinrange(nrows):each_data=sheet0.row_values(i)print

    2022年9月28日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号