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

在Java编程之中,我们通常都会接触到网络编程,那么不可避免地就会接触到Socket通信,下面我将对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进行简单的通信的实现就结束了~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容