关于Socket的解析以及双方即时通讯的java实现方法

 更新时间:2017年03月07日 10:38:02   作者:Mezereon  
本篇文章主要介绍了关于Socket的解析以及双方通讯的java实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。

在Java编程之中,我们通常都会接触到网络编程,那么不可避免地就会接触到Socket通信,下面我将对Socket进行简单的解析,并给出双方通讯的代码实现方案

首先我们来介绍一下整个Socket的通信过程

首先服务端先创建一个SocketServer,那么创建一个SocketServer需要我们指定端口号,如下

ServerSocket serverSocket=new ServerSocket(8888);

像上面这样我们就简单的开了一个端口号为8888的ServerSocket了

接下来我们需要去接收来自客户端的连接请求,也就是图中的Other Socket,我们可以利用SockerServer的accept方法来建立连接,并且这个方法会返回一个Socket,用于和Other Socker进行通信,简单来说,我们就是利用SockerServer来获取Socket,然后利用这个Socket和别人通信

接下来我们获取Socket的输入输出流,实现发送和接收信息,到此,我们已经知道两方进行Socket通信的基本思路了

接下来我们来看看关于ServerSocket以及Socket的一些关键方法

ServerSocket

首先我们看一下ServerSocket的构造方法,一共有4种:

1、无参的构造方法 :

ServerSocket(), 返回没有绑定端口号的ServerSocket实例
2、含一个参数的构造方法 :

ServerSocket(int port),返回绑定给定端口号的ServerSocket实例

3、含两个参数的构造方法 :

ServerSocket(int port, int backlog),返回绑定给定端口号的ServerSocket实例,并且设定同步队列(syns queue)的大小

4、含三个参数的构造方法:

ServerSocket(int port, int backlog, InetAddress bindAddr),返回绑定给定端口号的ServerSocket实例,并且设定同步队列(syns queue)的大小以及绑定给定的IP地址

主要看它的一些方法:

accept()

这个方法监听连接,一旦连接就返回一个Socket用于通信,需要注意的是,该方法为阻塞方法,如果没有连接程序并不会继续执行下去

close()

关闭Socket,如果accept还在阻塞的话,就会抛出一个SocketException的异常

关于ServerSocket就不多加赘述了,我们来看一看Socket

Socket

构造方法依然存在多种,这里只给出一个较为典型的

Socket(String host, int port),第一个参数是主机的IP地址作为字符串传入,第二个参数为端口号

getInputStream(), getOutputStream()

获得Socket的输入输出流,我们可以利用BufferReader以及PrintWriter来对这两个流进行操作,如下:

  BufferReader reader = new BufferedReader(
                  new InputStreamReader(socket.getInputStream()));
  PrintWriter writer = new PrintWriter(
                  new OutputStreamWriter(socket.getOutputStream()));

下面简单编写一个双方互相通信的java实现

首先是服务端

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* Created by Mezereon on 2017/3/1.
*/
public class TCPServer {
 private Socket socket;
 private ServerSocket serverSocket;
 private BufferedReader reader;
 private PrintWriter writer;
 private Scanner scanner = new Scanner(System.in);
 //开启服务
 public void run() throws IOException {
     startTheSocket();
 }
 public void startTheSocket() throws IOException {
   serverSocket=new ServerSocket(18080); //打开18080端口等待连接
   acceptTheSocket();//接受连接并且初始化Socket,reader,writer
   openTheNewThreadToGetMessageFromClient();
   while(true) {   
      getYourMessage();//获取键盘数据并作为输入
   }
 }
 //接受连接并且初始化Socket,reader,writer
 private void acceptTheSocket() throws IOException {
   socket=serverSocket.accept();//阻塞方法,用于接受Socket连接
   System.out.println("Some one connect me ,it is "+socket.getLocalSocketAddress());//打印地址
   System.out.println("It's port is "+socket.getPort());//打印端口号
   reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//获得输入流
   writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));//获得输出流
 }
 //扫描键盘并输入数据
 private void getYourMessage() throws IOException {
   String yourMessage = scanner.nextLine();
   checkYourMessage(yourMessage);//检查发送给客户端的信息
   writer.println(yourMessage);//发送信息
   writer.flush();//flush方法用于清空缓冲区,注意的是如果不flush你的信息可能发不出去一直存留在缓冲区
 }
 //用于检查是否退出
 private void checkYourMessage(String yourMessage) throws IOException {
   //关闭各种
   if (yourMessage.equals("exit")) {
     socket.close();
     writer.close();
     reader.close();
     System.exit(0);
   }
 }
 //开启一个新的线程来监听客户端发来的信息
 private void openTheNewThreadToGetMessageFromClient() throws IOException {
   //开启一个新的线程
   new Thread(new Runnable() {
     @Override
     public void run() {
       getTheMessageFromClient();
     }
   }).start();

 }
 //不断循环来获取客户端发来的信息
 private void getTheMessageFromClient() {
   while(true) {
     String messageFromClient = null;
     try {
       messageFromClient = reader.readLine();
     } catch (IOException e) {
       e.printStackTrace();
     }
     printTheMessage(messageFromClient);//打印客户端发来的信息
   }
 }
 //打印客户端发来的信息
 private void printTheMessage(String messageFromClient) {
   if(messageFromClient!=null)
     System.out.println("He say:"+messageFromClient);
 }    
}

然后开始编写客户端:

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

/**
 * Created by Mezereon on 2017/2/27.
 */
public class TCPClient {

  private Socket socket;
  private BufferedReader reader ;
  private PrintWriter writer;
  private Scanner scanner = new Scanner(System.in);

  //开启Socket来连接
  public void run() throws IOException{
      startTheSocket();
  }

  //开始连接服务端
  private void startTheSocket() throws IOException{
      toConnectTheServer();//创建Socket并初始化
      openTheThreadToReceiveInfoFromServer();//开启一个新的线程来接受服务端发来的信息

      //一个循环,用于读取键盘的输入
      while(true) {
        String yourMessage = scanner.nextLine();
        //不为空则发送信息
        if(yourMessage!=null) {
          writer.println(yourMessage);
          writer.flush();//记得flush清空缓冲区
        }
        //判断是否退出
        if (yourMessage.equals("exit")) {
          disConnect();
          System.exit(0);
        }
      }
  }

  //创建一个Socket来连接本机的18080端口的服务端并初始化reader和writer
  private void toConnectTheServer() throws IOException {
    socket=new Socket("127.0.0.1",18080);
    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
  }

  private void openTheThreadToReceiveInfoFromServer() throws IOException {
    new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          printMessage();//打印从服务端收到的信息
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }).start();
  }

  //循环不断读取服务端的信息
  private void printMessage() throws IOException {
    while (true) {
      String messageFromServer = null;
      try {
        messageFromServer = reader.readLine();//读取信息
        System.out.println("He say:" + messageFromServer);//打印信息
      } catch (IOException e) {
        e.printStackTrace();
      } catch (NullPointerException e) {

      }
      if(messageFromServer.equals("exit")){
        disConnect();//关闭连接
        System.exit(0);
      }
    }
  }

  //关闭各种
  private void disConnect() throws IOException {
    socket.close();
    reader.close();
    writer.close();
  }

}

至此,关于Socket通信简单的介绍以及利用java进行简单的通信的实现就结束了~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • JPA之QueryDSL-JPA使用指南

    JPA之QueryDSL-JPA使用指南

    Springdata-JPA是对JPA使用的封装,Querydsl-JPA也是基于各种ORM之上的一个通用查询框架,使用它的API类库可以写出Java代码的sql,下面就来介绍一下JPA之QueryDSL-JPA使用指南
    2023-11-11
  • spring cloud之eureka高可用集群和服务分区解析

    spring cloud之eureka高可用集群和服务分区解析

    这篇文章主要介绍了spring cloud之eureka高可用集群和服务分区解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Spring框架AOP面向切面编程原理全面分析

    Spring框架AOP面向切面编程原理全面分析

    这篇文章主要介绍了Spring框架AOP面向切面编程的全面分析,文中附含详细的示例代码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-09-09
  • Java Spring框架创建项目与Bean的存储与读取详解

    Java Spring框架创建项目与Bean的存储与读取详解

    本篇文章将介绍Spring项目的创建,IDEA国内源的配置以及Bean的存储与读取,所谓的Bean其实就是对象的意思,更详细地说Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象
    2022-07-07
  • SpringBoot应用自定义logback日志详解

    SpringBoot应用自定义logback日志详解

    默认情况下,SpringBoot内部使用logback作为系统日志实现的框架,将日志输出到控制台,不会写到日志文件。本篇文章主要讲解下如何自定义logabck.xml以及对logback文件中配置做一个详解,需要的可以参考一下
    2022-10-10
  • MyBatis实现动态查询、模糊查询功能

    MyBatis实现动态查询、模糊查询功能

    这篇文章主要介绍了MyBatis实现动态查询、模糊查询功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-06-06
  • Java线程让步yield用法实例分析

    Java线程让步yield用法实例分析

    这篇文章主要介绍了Java线程让步yield用法,结合实例形式分析了java中yield()方法的功能、原理及线程让步操作的相关实现技巧,需要的朋友可以参考下
    2019-09-09
  • 布隆过滤器详解以及其在Java中的实际应用

    布隆过滤器详解以及其在Java中的实际应用

    布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,这篇文章主要给大家介绍了关于布隆过滤器详解以及其在Java中的实际应用,需要的朋友可以参考下
    2023-12-12
  • Java 栈和队列的相互转换详解

    Java 栈和队列的相互转换详解

    栈和队列,严格意义上来说,也属于线性表,因为它们也都用于存储逻辑关系为 "一对一" 的数据,但由于它们比较特殊,因此将其单独作为一章,做重点讲解
    2022-02-02
  • Java实现调用jython执行python文件的方法

    Java实现调用jython执行python文件的方法

    这篇文章主要介绍了Java实现调用jython执行python文件的方法,结合实例形式分析了Java调用jython执行python文件的常见操作技巧及相关问题解决方法,需要的朋友可以参考下
    2018-03-03

最新评论