文章目录

  1. 前言
  2. Socket类
    2.1 Socket的通信过程
    2.2 控制Socket连接
    2.3 设置Socket的选项
  3. ServerSocket类
    3.1 构造ServerSocket
    3.2 ServerSocket的常用方法
    3.3 设置ServerSocket选项
  4. 基于TCP的BIO通信
    4.1 实现功能
    4.2 程序源代码
    4.3 程序效果截图

1. 前言

基于传输层协议TCP的网络通信是可靠的、有序的、差错控制的。TCP是面向连接的、可靠的流服务协议。TCP协议中,只有实现连接的双发才可以进行通信,因此广播和多播不是基于TCP的。下面首先介绍一些Socket和ServerSocket。
服务器、客户端建立通信的过程如下:

在这里插入图片描述

  1. 服务器网络接口的IP地址为10.1.1.1。服务器端应用程序在80端口运行服务,建立ServerSocket,并监听有无连接请求。
  2. 客户端必须知道服务器的IP地址或主机名、服务开放端口,客户端向服务器的服务Socket(10.1.1.1:80)发起请求。
  3. 服务器一旦接收该请求,就会在80端口上建立一个Socket,该Socket的本地地址为10.1.1.1:80,外部地址为客户端建立的Socket(client端IP地址,client端port)。客户端port通常由操作系统指定。
  4. 服务器每接收一个客户端的请求,就会在服务端口上建立一个Socket,这些Socket的本地地址相同,但外部地址各不相同。每个外部地址即各个客户端的本地Socket。这样服务器既可以监听服务请求,又可以和每个客户端进行独立的通信。
  5. 客户端通过本地Socket与服务器进行通信、读写信息。就像打电话一样,一个号码呼叫另一个号码,一旦被呼叫者接听,通信链路就建立起来了,双方就可以通话了。

2. Socket类

2.1 Socket的通信过程

在这里插入图片描述

2.2 控制Socket连接

获取Socket的输入流和输出流
服务端和客户端之间通信的Socket一旦连接,就会通过一对输入输出流进行通信。如同打电话时,一旦被叫放接听,双方通话的业务信道建立,就可以交流了。
Socket的getInputStream()方法和getOutputStream()方法分别实现获得输入流和输出流。

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));BufferedReader br = new BufferedReader(new IntputStreamReader(socket.getInputStream()));

获取Socket的地址端口信息
如果需要获得本地或者远程Socket的地址和端口信息,可以使用以下方法:

getInetAddress() //获得远程服务器的IP地址getPort() //获得远程服务器的端口getLocalAddress() //获得客户端本地的IP地址getLocalPort() //获得客户端本地的端口

关闭Socket
当客户端与服务器的通信结束时,应该关闭Socket,以释放Socket占用的包括

InputStream和OutputStream在内的各种资源。if(!s.isClosed()) s.close();//判断如果不是空的话则关闭

Socket的状态
Socket类提供了3中方法(isBound 、isClosed 和 isConnected)来判断Socket的状态。
isBound方法用来判断Socket的绑定状态,只要曾经绑定过,即使Socket已经关闭,仍然返回true。可以理解为本地是否曾经建立过到远程主机的Socket连接。
isClosed方法用来判断Socket是否已经关闭。
isConnected方法用来判断Socket的连接状态。和isBound方法一样,即使Socket已经关闭,仍然返回true,isConnected的状态不清楚。可以理解为到远程主机的Socket是否曾经连接过。

3. 基于TCP的BIO通信

3.1 实现功能

服务器创建服务并监听端口,与客户端建立连接,并向客户端转发消息,客户端输入quit命令即可退出。

3.2 程序源代码

Server类:

package com.company.bio;

import java.io.*;import java.net.ServerSocket;import java.net.Socket;

public class Server {    public static void main(String[] args){        final  String QUIT = "quit";        final int DEFAULT_PORT = 8888;        ServerSocket serverSocket = null;

        //绑定监听端口        try{            serverSocket = new ServerSocket(DEFAULT_PORT);            System.out.println("启动服务器,监听端口"+DEFAULT_PORT);

            while (true){                // 等待客户端连接                Socket socket = serverSocket.accept();                System.out.println("客户端[" + socket.getPort() + "]已连接");                //创建IO流                BufferedReader bufferedReader = new BufferedReader(                        new InputStreamReader(socket.getInputStream())                );                BufferedWriter bufferedWriter = new BufferedWriter(                        new OutputStreamWriter(socket.getOutputStream())                );

                String msg = null;                while ((msg = bufferedReader.readLine()) != null) {                    // 读取客户端发送的消息,当对方关闭时返回null

                    System.out.println("客户端["+socket.getPort()+"]:"+ msg);                    //回复客户发送的消息                    bufferedWriter.write("服务器:" + msg + "\n");                    bufferedWriter.flush(); //保证缓冲区的数据发送出去                    //查看客户端是否退出                    if(QUIT.equals(msg)){                        System.out.println("客户端["+socket.getPort()+"]已退出");                        break;                    }                }            }        }catch (IOException e){            e.printStackTrace();        }finally {            if (serverSocket != null){                try {                    serverSocket.close();                    System.out.println("关闭ServerSocket");                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

Client类:

package com.company.bio;

import java.io.*;import java.net.Socket;

public class Client {    public static void main(String[] args)  {        final  String QUIT = "quit";        final String DEFAULT_SERVER_HOST = "127.0.0.1";        final int DEFAULT_SERVER_PORT = 8888;        Socket socket = null;        BufferedWriter bufferedWriter = null;

        try{            // 创建socket            socket = new Socket(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT);            //创建IO流            BufferedReader bufferedReader = new BufferedReader(                new InputStreamReader(socket.getInputStream())            );            bufferedWriter = new BufferedWriter(                 new OutputStreamWriter(socket.getOutputStream())            );            //等待用户输入信息            BufferedReader consolReader = new BufferedReader(                    new InputStreamReader(System.in)            );            while (true) {                String input = consolReader.readLine();                //发送消息给服务器                bufferedWriter.write(input + "\n");                bufferedWriter.flush();                //读取服务器返回的消息                String msg = bufferedReader.readLine();                System.out.println(msg);

                //查看用户是否退出                if(QUIT.equals(input))break;            }        }catch (IOException e){            e.printStackTrace();        }finally {            if(bufferedWriter != null){                try {                    bufferedWriter.close();                    System.out.println("关闭socket");                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

3.3 程序效果截图
Client:

在这里插入图片描述
Server:
在这里插入图片描述

更多资源和教程请关注公众号:非科班的科班。
如果觉得我写的还可以请给个赞,谢谢大家,你的鼓励是我创作的动力

基于BIO的实时Socket读写操作的更多相关文章

  1. 一个I/O线程可以并发处理N个客户端连接和读写操作 I/O复用模型 基于Buf操作NIO可以读取任意位置的数据 Channel中读取数据到Buffer中或将数据 Buffer 中写入到 Channel 事件驱动消息通知观察者模式

    Tomcat那些事儿 https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650860016&idx=2&sn=549 ...

  2. NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))

    NX二次开发API里没有对EXCAL读写操作的相关函数,市面上有很多种方法去实现,比如UFUN调KF,ODBC,OLE(COM组件)等等.这里我是用的OLE(COM组件)方式去做的,这种在VC上创建的 ...

  3. NX二次开发-基于NX开发向导模板的NX对Excel读写操作(OLE方式(COM组件))

    在看这个博客前,请读者先去完整看完:NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))https://ufun-nxopen.blog.csdn.net/article ...

  4. linux下mysql基于mycat做主从复制和读写分离之基础篇

    Linux下mysql基于mycat实现主从复制和读写分离1.基础设施 两台虚拟机:172.20.79.232(主) 172.20.79.233(从) 1.1软件设施 mysql5.6.39 , my ...

  5. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  6. 基于AHB总线的master读写设计(Verilog)

    一.AHB总线学习 1. AHB总线结构 如图所示,AHB总线系统利用中央多路选择机制实现主机与从机的互联问题.从图中可以看出,AHB总线结构主要可分为三部分:主机.从机.控制部分.控制部分由仲裁器. ...

  7. socket读写返回值的处理

    在调用socket读写函数read(),write()时,都会有返回值.如果没有正确处理返回值,就可能引入一些问题 总结了以下几点 1当read()或者write()函数返回值大于0时,表示实际从缓冲 ...

  8. 基于Xenomai的实时Linux分析与研究

    转自:http://blog.csdn.net/cyberlabs/article/details/6967192 引 言 随着嵌入式设备的快速发展,嵌入式设备的功能和灵活性要求越来越高,很多嵌入式设 ...

  9. berkerly db 中简单的读写操作(有一些C的 还有一些C++的)

    最近在倒腾BDB,才发现自己确实在C++这一块能力很弱,看了一天的api文档,总算是把BDB的一些api之间的关系理清了,希望初学者要理清数据库基本知识中的环境,句柄,游标的基本概念,这样有助于你更好 ...

随机推荐

  1. iptables总结,开启端口,查看端口占用情况

    Centos查看端口占用情况和开启端口命令 Centos查看端口占用情况命令,比如查看80端口占用情况使用如下命令: lsof -i tcp:80 列出所有端口 netstat -ntlp mac上查 ...

  2. boostrap-非常好用但是容易让人忽略的地方【4】:Font Awesome

    font-awesome基本用法 官方代码传送门 font-awesome在bootstrap中的特殊用法(这个才是重点) 要点归纳1(官方) 官方代码传送门 要点归纳2(我的) <a href ...

  3. Linux基础:Linux下常用命令

    常用命令 shutdown ​ 用来系统关机命令.shutdown指令可以关闭所有程序,并依用户的需要,进行重新开机或关机的动作. ​ shutdown (选项)(参数) -c: 当执行"s ...

  4. 记录安装Python第三方包“tesserocr”的方法和遇到的坑

    1. 环境: 系统环境:Win7 32 位系统 Python版本: 3.6.5        虚拟环境为:Miniconda3 2. 共需要安装的模块: a. tesserocr b. tessera ...

  5. Spring||Interview

    1.依赖注入(DI)(IOC) 对象本身不负责对象的创建和维护,将控制权转交给外部的容器实现,降低程序的耦合度,只提供java方法让容器决定依赖关系,依赖关系的对象通过JavaBean属性或者构造函数 ...

  6. Mysql的SQL优化指北

    概述 在一次和技术大佬的聊天中被问到,平时我是怎么做Mysql的优化的?在这个问题上我只回答出了几点,感觉回答的不够完美,所以我打算整理一次SQL的优化问题. 要知道怎么优化首先要知道一条SQL是怎么 ...

  7. Gif动图压缩java版

    简单说明下,如果不是压缩动图的话只用java本身的包足够实现压缩和截取图片了,为了能够压缩gif动图,这里引用了两个文件 AnimatedGifEncoder 和 GifDecoder, 先用Deco ...

  8. Autofac总结

    Autofac 介绍|术语 控制反转:IOC和DI IOC 调用者不再创建(不自己new)被调用者的实例,而是交给容器去创建(AutoFac就充当这里的容器),这就是控制反转 控制反转中引入的第三方对 ...

  9. 【DDD】持久化领域对象的方法实践

    [toc] 概述 在实践领域驱动设计(DDD)的过程中,我们会根据项目的所在领域以及需求情况捕获出一定数量的领域对象.设计得足够好的领域对象便于我们更加透彻的理解业务,方便系统后期的扩展和维护,不至于 ...

  10. Sorted 内置函数的排序使用

    Sorted 内置函数的排序使用 Sorted 排序列表 1.倒序对列表进行排序 # 对列表进行降序序排序 list = [1,3,4,23,6,7] list = sorted(list,rever ...