java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
本篇文章主要介绍了 JAVA 实现基于 Tcp 协议的简单 Socket 通信实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~
今天来讲下关于 Socket 通信的简单应用,关于什么是 Socket 以及一些网络编程的基础,这里就不提了,只记录最简单易懂实用的东西。
1、首先先来看下基于 TCP 协议 Socket 服务端和客户端的通信模型:
Socket 通信步骤:(简单分为 4 步)
1. 建立服务端 ServerSocket 和客户端 Socket
2. 打开连接到 Socket 的输出输入流
3. 按照协议进行读写操作
4. 关闭相对应的资源
2、相关联的 API:
1. 首先先来看下 ServerSocket
类 ServerSocket
此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
服务器套接字的实际工作由 SocketImpl 类的实例执行。应用程序可以更改创建套接字实现的套接字工厂来配置它自身,从而创建适合本地防火墙的套接字。
一些重要的方法:(具体大家查看官方 api 吧)
- ServerSocket(int port, int backlog)
利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
- bind(SocketAddress endpoint, int backlog)
将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
侦听并接受到此套接字的连接
返回此服务器套接字的本地地址。
关闭此套接字。
2. 再来看下 Socket
类 Socket
此类实现客户端套接字(也可以就叫 "套接字")。套接字是两台机器间通信的端点。
套接字的实际工作由 SocketImpl 类的实例执行。应用程序通过更改创建套接字实现的套接字工厂可以配置它自身,以创建适合本地防火墙的套接字。
一些重要的方法:(具体大家查看官方 api 吧)
- Socket(InetAddress address, int port)
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
返回套接字连接的地址。
此套接字的输入流置于 "流的末尾"。
禁用此套接字的输出流。
关闭此套接字。
3、代码实现:(注释很全,这里就不详细多说了)
服务端 Server.java
1. 创建 ServerSocket 对象,绑定并监听端口
2. 通过 accept 监听客户端的请求
3. 建立连接后,通过输出输入流进行读写操作
4. 关闭相关资源
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class Server {
- /**
- * Socket服务端
- */
- public static void main(String[] args) {
- try {
- ServerSocket serverSocket = new ServerSocket(8888);
- System.out.println("服务端已启动,等待客户端连接..");
- Socket socket = serverSocket.accept(); //侦听并接受到此套接字的连接,返回一个Socket对象
- //根据输入输出流和客户端连接
- InputStream inputStream = socket.getInputStream(); //得到一个输入流,接收客户端传递的信息
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream); //提高效率,将自己字节流转为字符流
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader); //加入缓冲区
- String temp = null;
- String info = "";
- while ((temp = bufferedReader.readLine()) != null) {
- info += temp;
- System.out.println("已接收到客户端连接");
- System.out.println("服务端接收到客户端信息:" + info + ",当前客户端ip为:" + socket.getInetAddress().getHostAddress());
- }
- OutputStream outputStream = socket.getOutputStream(); //获取一个输出流,向服务端发送信息
- PrintWriter printWriter = new PrintWriter(outputStream); //将输出流包装成打印流
- printWriter.print("你好,服务端已接收到您的信息");
- printWriter.flush();
- socket.shutdownOutput(); //关闭输出流
- //关闭相对应的资源
- printWriter.close();
- outputStream.close();
- bufferedReader.close();
- inputStream.close();
- socket.close();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
客户端 Client.java
1. 创建 Socket 对象,指定服务端的地址和端口号
2. 建立连接后,通过输出输入流进行读写操作
3. 通过输出输入流获取服务器返回信息
4. 关闭相关资源
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.Socket;
- import java.net.UnknownHostException;
- public class Client {
- /**
- * Socket客户端
- */
- public static void main(String[] args) {
- try {
- //创建Socket对象
- Socket socket = new Socket("localhost", 8888);
- //根据输入输出流和服务端连接
- OutputStream outputStream = socket.getOutputStream(); //获取一个输出流,向服务端发送信息
- PrintWriter printWriter = new PrintWriter(outputStream); //将输出流包装成打印流
- printWriter.print("服务端你好,我是Balla_兔子");
- printWriter.flush();
- socket.shutdownOutput(); //关闭输出流
- InputStream inputStream = socket.getInputStream(); //获取一个输入流,接收服务端的信息
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream); //包装成字符流,提高效率
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader); //缓冲区
- String info = "";
- String temp = null; //临时变量
- while ((temp = bufferedReader.readLine()) != null) {
- info += temp;
- System.out.println("客户端接收服务端发送信息:" + info);
- }
- //关闭相对应的资源
- bufferedReader.close();
- inputStream.close();
- printWriter.close();
- outputStream.close();
- socket.close();
- } catch(UnknownHostException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
4、效果截图:
服务端:
客户端:
以上代码实现了单客户端和服务端的连接,若要实现多客户端操作,需要涉及到多线程,只要你把每个接收到的 Socket 对象单独开一条线程操作,然后用一个死循环 while(true) 去监听端口就行,这边直接给代码了
线程操作类:SocketThread.java
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.Socket;
- /**
- * Socket多线程处理类 用来处理服务端接收到的客户端请求(处理Socket对象)
- */
- public class SocketThread extends Thread {
- private Socket socket;
- public SocketThread(Socket socket) {
- this.socket = socket;
- }
- public void run() {
- // 根据输入输出流和客户端连接
- try {
- InputStream inputStream = socket.getInputStream();
- // 得到一个输入流,接收客户端传递的信息
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream); // 提高效率,将自己字节流转为字符流
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader); // 加入缓冲区
- String temp = null;
- String info = "";
- while ((temp = bufferedReader.readLine()) != null) {
- info += temp;
- System.out.println("已接收到客户端连接");
- System.out.println("服务端接收到客户端信息:" + info + ",当前客户端ip为:" + socket.getInetAddress().getHostAddress());
- }
- OutputStream outputStream = socket.getOutputStream(); // 获取一个输出流,向服务端发送信息
- PrintWriter printWriter = new PrintWriter(outputStream); // 将输出流包装成打印流
- printWriter.print("你好,服务端已接收到您的信息");
- printWriter.flush();
- socket.shutdownOutput(); // 关闭输出流
- // 关闭相对应的资源
- bufferedReader.close();
- inputStream.close();
- printWriter.close();
- outputStream.close();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
服务端类:Server.java
- import java.io.IOException;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class Server {
- /**
- * Socket服务端
- */
- public static void main(String[] args) {
- try {
- ServerSocket serverSocket = new ServerSocket(8888);
- System.out.println("服务端已启动,等待客户端连接..");
- while (true) {
- Socket socket = serverSocket.accept(); // 侦听并接受到此套接字的连接,返回一个Socket对象
- SocketThread socketThread = new SocketThread(socket);
- socketThread.start();
- }
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
客户端类: Client.java
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.Socket;
- import java.net.UnknownHostException;
- public class Client {
- /**
- * Socket客户端
- */
- public static void main(String[] args) {
- try {
- //创建Socket对象
- Socket socket = new Socket("localhost", 8888);
- //根据输入输出流和服务端连接
- OutputStream outputStream = socket.getOutputStream(); //获取一个输出流,向服务端发送信息
- PrintWriter printWriter = new PrintWriter(outputStream); //将输出流包装成打印流
- printWriter.print("服务端你好,我是客户1");
- printWriter.flush();
- socket.shutdownOutput(); //关闭输出流
- InputStream inputStream = socket.getInputStream(); //获取一个输入流,接收服务端的信息
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream); //包装成字符流,提高效率
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader); //缓冲区
- String info = "";
- String temp = null; //临时变量
- while ((temp = bufferedReader.readLine()) != null) {
- info += temp;
- System.out.println("客户端接收服务端发送信息:" + info);
- }
- //关闭相对应的资源
- bufferedReader.close();
- inputStream.close();
- printWriter.close();
- outputStream.close();
- socket.close();
- } catch(UnknownHostException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
看下效果实现图:
这里只是抛砖引玉,在实际开发中,基于 Socket 编程,一般传递的并非字符串,很多情况下是对象,我们可以使用 ObjectOutputStream 将输出流对象序列化。
例如:
- OutputStream outputStream = socket.getOutputStream();
- ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
- User user = new User("admin", "123456");
- objectOutputStream.writeObject(user);
来源: http://www.phperz.com/article/17/1224/358739.html