对于Socket还不太了解的建议先看看我前面一篇文章 Socket网络知识学习基础
Socket通信最基本的一个前提就是需要有唯一的标示一个进程,而进程可以利用ip地址+协议+端口号来组成,因此我们首先需要知道服务端的ip地址,客户端才能与服务端进行连接
获取ip地址需要这两个类
InetAddress InetAddress是java对IP地址的封装.NetworkInterface NetworkInterface类可以得到本机所有的物理网络接口和虚拟机等软件利用本机的物理网络接口创建的逻辑网络接口的信息使用InetAddress配合NetworkInterface使用来获取本地ip地址代码:
public static String getIP() { String ip = null; try { Enumeration en = NetworkInterface.getNetworkInterfaces(); while (en.hasMoreElements()) { NetworkInterface ni = (NetworkInterface) en.nextElement(); if (ni.isVirtual() || "virbr0".equals(ni.getName())) { continue; } Enumeration<InetAddress> ee = ni.getInetAddresses(); while (ee.hasMoreElements()) { InetAddress ia = ee.nextElement(); if (!ia.isLoopbackAddress() && !(ia instanceof Inet6Address) ) { ip = ia.getHostAddress(); } } } } catch (Exception e) { e.PRintStackTrace(); } return ip; }主要思路是通过NetworkInterface获得所有网络接口的信息然后通过遍历赋值给InetAddress类找到真实网卡的ip地址
Socket服务端和客户端通信模型:
简单的说Socket之间通信的步骤是这样的:
建立服务端ServerSocket和客户端Socket打开连接到Socket的输出输入流按照协议进行读写操作关闭相对应的资源Socket通信时需要用到以下几个类:
ServerSocket 用于在服务端指定端口建立一个监听服务Socket 用于服务器端与客户端之间相互通信InputStream OutputStream 处理字节流的抽象类,字节流的所有类的超类InputStreamReader OutputStreamWriter 处理字符流的抽象类,字节流与字符流转换的桥梁BufferedReader BufferedWriter BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,readLine读取一个文本行, 从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取 BufferedWriter 由Writer 类扩展而来,提供通用的缓冲方式文本写入, newLine使用平台自己的行分隔符, 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入PrintWriter 与BufferedWriter类似,不过PrintWriter提供println()方法可以写不同平台的换行符,而BufferedWriter可以任意设定缓冲大小然后我们来看个服务端与客户端建立Socket连接的实例:
服务端主要代码
public SocketTest() throws IOException { //1.创建一个服务端Socket,即ServerSocket,指定绑定的端口,并监听此端口 ServerSocket serverSocket = new ServerSocket(SocketTool.PORT); String ip = SocketTool.getIP(); System.out.println("1.服务端已就绪,等待客户端接入,服务端ip地址: " + ip); //2.调用accept()等待客户端连接,建立连接后,accept()返回一个最近创建的Socket对象, //该Socket对象绑定了客户程序的IP地址或端口号 Socket socket = serverSocket.accept(); //3.连接后获取输入流,读取客户端信息 InputStream is= socket.getInputStream(); //获取输入流 InputStreamReader isr = new InputStreamReader(is, "UTF-8"); BufferedReader br = new BufferedReader(isr); String info; while ((info = br.readLine()) != null) {//循环读取客户端的信息 System.out.println("3.服务端接收客户端信息: " + info); } socket.shutdownInput();//关闭输入流 //4.服务端收到客户端消息后返回一条消息 OutputStream os = socket.getOutputStream();//字节输出流 PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流 pw.write("服务端 " + ip + " 返回消息!"); pw.flush(); System.out.println("4.服务端返回信息给客户端: " + "服务端 " + ip + " 返回消息!"); //socket.shutdownOutput();//关闭输出流 socket.close(); }服务端监听端口,等待有客户端连接后,读取输入流获得客户端发送的信息,然后返回一条信息给客户端,发送后关闭连接
客户端主要代码
private void acceptServer() throws IOException { //1.创建客户端Socket,指定服务器地址和端口 //Log.i(TAG, "客户端:before socket"); Socket socket = new Socket(SocketTool.HOST, SocketTool.PORT); socket.setSoTimeout(5000); //Log.i(TAG, "客户端:after socket"); //2.获取输出流,向服务器端发送信息 OutputStream os = socket.getOutputStream();//字节输出流 PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流 //获取客户端的IP地址 String ip = SocketTool.getIP(); //3.客户端发送消息 pw.write("客户端 " + ip + " 接入服务器!"); pw.flush(); Log.i(TAG, "2.客户端发送信息: 客户端 " + ip + " 接入服务器!"); socket.shutdownOutput();//关闭输出流 //4.客户端等待服务端返回的消息 InputStream is = socket.getInputStream(); //获取输入流; InputStreamReader isr = new InputStreamReader(is, "UTF-8"); BufferedReader br = new BufferedReader(isr); String info; while ((info = br.readLine()) != null) {//循环读取客户端的信息 Log.i(TAG, "5.客户端接收服务端信息: " + info); } //socket.shutdownInput();//关闭输入流 socket.close(); }客户端在连接服务端成功后发送一条消息给服务端,然后等待服务端发送消息,收到后打印出来
完整示例: Android端代码 JAVA端代码
新闻热点
疑难解答