0
点赞
收藏
分享

微信扫一扫

通信编程之java socket初探

念川LNSC 2022-01-28 阅读 61

最近在思考一些软件的实现原理,研究一下那些热门软件是怎么开发出来的,颇有点意思。回顾每天使用的软件,发现平时用的最多的软件应该是通信软件了,如微信、钉钉等,于是在想,这些通信软件是怎么开发出来的,使用了哪些技术?平时大家开发软件的工作大部分是CRUD,对一些不是自己的工作领域,一些底层技术研究的比较少,所以利用业余时间也对一些底层技术和自己感兴趣的软件做些研究。这篇是对通信软件的初探。

Java通信软件的开发技术从socket说起,下面对socket技术做些基础的了解和练习。

先看一下实战的效果图:

 

一、socket是什么?

网络通信里面,我们都听过TCP/UDP,HTTP,那么Socket是什么?Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。通常可用于通信软件开发,RPC协议开发,文件传输开发等。Socket使用中主要分为ServerSocket和Socket, ServerSocket类表示 Socket 服务器端,Socket 类表示 Socket 客户端。

二、socket的交互流程

socket的使用流程是什么样的呢?

两者之间的交互过程如下:
1.服务器端创建一个 ServerSocket(服务器端套接字),调用 accept() 方法等待客户端来连接。
2.客户端程序创建一个 Socket,请求与服务器建立连接。
3.服务器接收客户的连接请求,同时创建一个新的 Socket 与客户建立连接,服务器继续等待新的请求。

4.使用网络I/O来操作消息的发送和接收。如BufferedReader读/BufferedWriter写。

如下是socket的客户端和服务端的交互示意图。

 

三、实战演练

了解了socket的知识后,我们来进行一些实战练习。socket的通信实现分为服务端和客户端两个应用,在部署层面是两个独立的应用,我们先实现服务端的代码,如下:

package socketStudy;

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

/**
 * socket 服务端
 * @author xiaoming
 * @version 1.0
 * @date 2022-01-28
 */
public class CommunicationServer {

    public static String socketserver_ip = "127.0.0.1";
    public static int socketserver_port = 8881;

    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(socketserver_port);
            System.out.println("CommunicationServer启动服务器....端口为:"+socketserver_port+" wait connect...");
            Socket s = ss.accept();
            System.out.println("收到客户端连接,客户端:"+s.getInetAddress().getHostAddress()+"已连接到服务器");

            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            //读取客户端发送来的消息
            String mess = br.readLine();
            System.out.println("【收到客户端信息】信息为:"+mess);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            bw.write("【服务端】已收到客户端发送消息,消息为:"+mess+"\n");
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

首先,启动服务端socket程序,通过初始化ServerSocket(int port)实例就客户创建一个socket的服务端,port是服务端提供的端口号,对外提供的服务ip地址就是本机的IP地址,这里采用本地连接(127.0.0.1)。然后通过ServerSocket.accept()方法实现监听客户端的连接,之后就是使用BufferedReader、BufferedWriter来收发消息了。

下面在看看socket的客户端代码:

package socketStudy;

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

/**
 * socket客户端
 * @author xiaoming
 * @version 1.0
 * @date 2022-01-28
 */
public class CommunicationClient {
    public static void main(String[] args) {
        try {
            //连接socket服务端
            Socket s = new Socket(CommunicationServer.socketserver_ip,CommunicationServer.socketserver_port);

            //构建IO
            InputStream inp = s.getInputStream();//输入流,收到的信息
            OutputStream outp = s.getOutputStream();//输出流,发出去的消息

            //向服务器端发送一条消息
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outp));
            bw.write("测试客户端和服务器通信,服务器接收到消息返回到客户端\n");
            bw.flush();

            //读取服务器返回的消息
            BufferedReader br = new BufferedReader(new InputStreamReader(inp));
            String mess = br.readLine();
            System.out.println("【收到服务器信息】:"+mess);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端首先使用new Socket(String ip,int port)来连接服务端的ip和端口号。然后使用BufferedReader、BufferedWriter来收发消息。先启动CommunicationServer.java,启动成功后,等待连接,会看到日志:

"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" ...
CommunicationServer启动服务器....端口为:8881 wait connect...

这个时候服务端还没有任何客户端连接,再启动客户端程序,运行CommunicationClient.java,启动成功后,会看到服务端日志更新为如下:

"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" ...
CommunicationServer启动服务器....端口为:8881 wait connect...
收到客户端连接,客户端:127.0.0.1已连接到服务器
【收到客户端信息】信息为:测试客户端和服务器通信,服务器接收到消息返回到客户端

同时服务端日志展示为:

"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" ...
【收到服务器信息】:【服务端】已收到客户端发送消息,消息为:测试客户端和服务器通信,服务器接收到消息返回到客户端

这样一个完整的socket的服务端、客户端程序通信就完成了。

四、学习到的知识和问题总结

1、学习到的知识

学到了socket的原理及初步用法,及实战中的容易出错点及纠正方法。

思考:怎么样实现持续的收发消息,及多客户端之间的通信呢?

2、遇到的问题

(1)、起类名字的冲突

自己新建了一个socket服务端类叫ServerSocket,结果和socket的服务端实现类冲突了,尴尬。。。

(2)、发送消息和收到的消息处理搞反了,这个很容易混淆。

好的方法是在参数定义上写清楚一些,并加上注释。

InputStream receiveMsgInputS //输入流,收到的信息
OutputStream sendMsgOutS //输出流,发出去的消息

(3)、程序运行的收发过程混乱

由于是服务端客户端模式,都会来回的收发消息,如果打印的日志不清晰的话,容易搞不清消息收发的过程,网上很多例子都能实现,但是探究其过程,对于初学者还是容易混淆的。建议在每个程序的入口和结尾出打印关键日志,日志中加上处理者的角色,处理的事情,及返回的结果,这样对与学习和排查问题都有很大的好处。

举报

相关推荐

0 条评论