socket系统化入门
Posted newandhui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket系统化入门相关的知识,希望对你有一定的参考价值。
1.简单socket完成消息发送与接收
服务端:
package com.wfd360.com.socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-01 15:14 * @Description: */ public class ServerSocketDemo { /** * ServerSocket 的构造方法如下所示。 * ServerSocket():无参构造方法。 * ServerSocket(int port):创建绑定到特定端口的服务器套接字。 * ServerSocket(int port,int backlog):使用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口。 * ServerSocket(int port,int backlog,InetAddress bindAddr):使用指定的端口、监听 backlog 和要绑定到本地的 IP 地址创建服务器。 * <p> * =================================================================================================================== * ServerSocket 的常用方法如下所示。 * Server accept():监听并接收到此套接字的连接。 * void bind(SocketAddress endpoint):将 ServerSocket 绑定到指定地址(IP 地址和端口号)。 * void close():关闭此套接字。 * InetAddress getInetAddress():返回此服务器套接字的本地地址。 * int getLocalPort():返回此套接字监听的端口。 * SocketAddress getLocalSoclcetAddress():返回此套接字绑定的端口的地址,如果尚未绑定则返回 null。 * int getReceiveBufferSize():获取此 ServerSocket 的 SO_RCVBUF 选项的值,该值是从 ServerSocket 接收的套接字的建议缓冲区大小。 * * @param args 服务端设计步骤: * 1.创建socket服务端 * 2.监听客户端 * 3.获取输入流 * 4.输出 */ public static void main(String[] args) { ServerSocket serverSocket = null; Socket server = null; BufferedReader reader = null; BufferedWriter writer = null; try { //1.建立socket服务器 serverSocket = new ServerSocket(1001); System.out.println("服务端创建成功----"); while (true) { //2.监听客户端连接 server = serverSocket.accept(); //3.读取客户端数据 reader = new BufferedReader(new InputStreamReader(server.getInputStream())); String s = reader.readLine(); System.out.println("服务端收到数据:" + s); //4.响应客户端 writer = new BufferedWriter(new OutputStreamWriter(server.getOutputStream())); writer.write("已经收到数据[" + s + "] "); //清除缓存 writer.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try { //关闭资源 if (writer != null) { writer.close(); } if (reader != null) { reader.close(); } if (server != null) { server.close(); } if (serverSocket != null) { serverSocket.close(); } } catch (Exception e) { e.printStackTrace(); } } } }
客户端:
package com.wfd360.com.socket; import java.io.*; import java.net.Socket; /** * @Copyright * @Author: LI DONG PING * @Date: 2019-09-01 15:50 * @Description: */ public class ClientSocketDemo { /** * 客户端设计逻辑: * 1.创建socket通信,设置IP和端口 * 2.建立IO输出流,向服务端发送数据 * 3.建立IO输入流,读取服务端应答的数据 * * @param args */ public static void main(String[] args) { Socket socket = null; BufferedWriter writer = null; BufferedReader reader = null; try { //1.创建socket通信 socket = new Socket("localhost", 1001); //2.建立IO输出流,向服务端发送数据 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //注意这里必须加 ,因为是按照行读取 writer.write("短信发送2 "); writer.flush(); //3.建立IO输入流,读取服务端应答的数据 reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String s = reader.readLine(); System.out.println("客户端收到数据:" + s); } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } } catch (Exception e) { e.printStackTrace(); } } } }
2.socket中的常用io操作
常用类:https://www.cnblogs.com/newAndHui/p/11514269.html
案例:
package com.wfd360.com.io; import org.junit.Test; import java.io.*; import java.util.ArrayList; import java.util.List; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-12 11:15 * @Description: */ public class FileDemo { /** * 需求: * 将a.txt 复制到 b.txt * * @param args */ public static void main(String[] args) throws Exception { } @Test public void test2() throws Exception { // String filePath="E:\\test\\day18_数据结构.docx"; String filePath="E:\\test\\a.txt"; String filePathNew="E:\\test\\b.txt"; //1.读取本地文件a File file = new File(filePath); DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file)); //读取文件名 // String fileName = dataInputStream.readUTF(); //读取文件大小 // long fileSize = dataInputStream.readLong(); // System.out.println("fileName="+fileName+",fileSize="+fileSize); //准备写入文件对象 File fileNew = new File(filePathNew); // fileNew.createNewFile(); DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(fileNew)); //按照字节读取文件 byte[] aByte = new byte[128]; System.out.println("length="+aByte.length); int read = dataInputStream.read(aByte, 0, aByte.length); while (read!=-1){ //当前文件内容 String s = new String(aByte,"gbk"); System.out.println("read="+read+"s="+s); //写入文件 dataOutputStream.write(aByte,0,read); dataOutputStream.flush(); read = dataInputStream.read(aByte, 0, aByte.length); } //2.写入到本地文件b } /** * 需求: * 将a.txt 复制到 b.txt * 使用:FileInputStream,FileOutputStream * * @throws Exception */ @Test public void test1() throws Exception { //1:读取a.txt中的内容 //1.1.建立文件 File file = new File("D:\\test\\a.txt"); //1.2.读取文件内容 字节流 FileInputStream fileInputStream = new FileInputStream(file); //1.3.转变为处理流 gb2312 BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream, "gbk")); //1.4.按照行读取数据 List<String> content = new ArrayList<String>(); String line = reader.readLine(); while (line != null) { System.out.println("line=" + line); content.add(line); //读取下一行 line = reader.readLine(); } //2:写入到b.txt中 //2.1.创建文件 File fileB = new File("D:\\test\\b.txt"); boolean newFile = fileB.createNewFile(); System.out.println("newFile=" + newFile); //2.2.创建写入文件字节流 FileOutputStream fileOutputStream = new FileOutputStream(fileB); //2.3.转变为处理流 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "gbk")); for (String s : content) { writer.write(s); } writer.flush(); writer.close(); } }
3.socket中java对象传送
java对象
package com.wfd360.com.socketJava.model; import java.io.Serializable; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-12 17:48 * @Description: */ public class User implements Serializable { private String name; private Integer age; public User() { } public User(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "name=‘" + name + ‘‘‘ + ", age=" + age + ‘}‘; } }
服务端:
package com.wfd360.com.socketJava; import com.wfd360.com.socketJava.model.User; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-01 15:14 * @Description: */ public class ServerSocketDemo { /** * @param args 服务端设计步骤: * 1.创建socket服务端 * 2.监听客户端 * 3.获取输入流 * 4.输出 */ public static void main(String[] args) { ServerSocket serverSocket = null; Socket server = null; ObjectInputStream objectInputStream = null; ObjectOutputStream objectOutputStream = null; try { //1.建立socket服务器 serverSocket = new ServerSocket(1002); System.out.println("服务端创建成功----"); while (true) { //2.监听客户端连接 server = serverSocket.accept(); //3.读取客户端数据 objectInputStream = new ObjectInputStream(server.getInputStream()); User user = (User) objectInputStream.readObject(); System.out.println("服务端收到数据:" + user); //4.响应客户端 objectOutputStream = new ObjectOutputStream(server.getOutputStream()); user.setName("我来做服务端"); objectOutputStream.writeObject(user); //清除缓存 objectOutputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { try { //关闭资源 if (objectOutputStream != null) { objectOutputStream.close(); } if (objectInputStream != null) { objectInputStream.close(); } if (server != null) { server.close(); } if (serverSocket != null) { serverSocket.close(); } } catch (Exception e) { e.printStackTrace(); } } } }
客户端:
package com.wfd360.com.socketJava; import com.wfd360.com.socketJava.model.User; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-01 15:50 * @Description: */ public class ClientSocketDemo { /** * 客户端设计逻辑: * 1.创建socket通信,设置IP和端口 * 2.建立IO输出流,向服务端发送数据 * 3.建立IO输入流,读取服务端应答的数据 * * @param args */ public static void main(String[] args) { Socket socket = null; ObjectOutputStream writer = null; ObjectInputStream reader = null; try { //1.创建socket通信 socket = new Socket("localhost", 1002); //2.建立IO输出流,向服务端发送数据 writer = new ObjectOutputStream(socket.getOutputStream()); writer.writeObject(new User("无忌", 19)); writer.flush(); //3.建立IO输入流,读取服务端应答的数据 reader = new ObjectInputStream(socket.getInputStream()); User o = (User) reader.readObject(); System.out.println("==>" + o); } catch (Exception e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } } catch (Exception e) { e.printStackTrace(); } } } }
4.多线程下的socket
多线程处理类
package com.wfd360.com.socketThread.thread; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; public class HandleServerThread extends Thread { private Socket socket; public HandleServerThread(){ } public HandleServerThread(Socket socket){ this.socket=socket; } @Override public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String s = reader.readLine(); System.out.println("收到连接的客户端:ip="+socket.getInetAddress()+" port:"+socket.getPort()+" s="+s); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("服务端收到的数据为[" + s + "] "); writer.flush(); writer.close(); reader.close(); socket.close(); } catch (Exception e) { e.printStackTrace(); } } }
服务端:
package com.wfd360.com.socketThread; import com.wfd360.com.socketThread.thread.HandleServerThread; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-01 15:14 * @Description: */ public class ServerSocketDemo { static int port = 1103; /** * 服务端开启多线程 * * @param args */ public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(port); int i=1; System.out.println("服务端已启动----"+i); while (true) { System.out.println("等待客户端连接---"+i); Socket socket = server.accept(); System.out.println("已连接---"+i); HandleServerThread thread = new HandleServerThread(socket); thread.start(); i++; } } }
客户端:
package com.wfd360.com.socketThread; import java.io.*; import java.net.Socket; /** * @Copyright (C) * @Author: LI DONG PING * @Date: 2019-09-01 15:50 * @Description: */ public class ClientSocketDemo { static String host = "192.168.0.103"; static Integer port = 1103; /** * 客户端设计逻辑: * 1.创建socket通信,设置IP和端口 * 2.建立IO输出流,向服务端发送数据 * 3.建立IO输入流,读取服务端应答的数据 * * @param args */ public static void main(String[] args) { Socket socket = null; BufferedWriter writer = null; BufferedReader reader = null; try { while (true) { //1.创建socket通信 socket = new Socket(host, port); //2.建立IO输出流,向服务端发送数据 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //读取控制台输入的数据 System.out.print("请输入要发送的数据(结束请输入exit):"); String sysIn = new BufferedReader(new InputStreamReader(System.in)).readLine(); System.out.println("sysIn=" + sysIn); if ("exit".equals(sysIn)) { break; } //注意这里必须加 ,因为是按照行读取 writer.write("向服务端发送数据:" + sysIn + " "); writer.flush(); //3.建立IO输入流,读取服务端应答的数据 reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String s = reader.readLine(); System.out.println("客户端收到数据:" + s); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } } catch (Exception e) { e.printStackTrace(); } } } }
5.socket下的多线程文件传输
多线程处理类
package com.wfd360.com.socketFile.thread; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.net.Socket; public class HandleServerThread extends Thread { private Socket socket; public HandleServerThread() { } public HandleServerThread(Socket socket) { this.socket = socket; } /** * 将文件保存到本地 */ @Override public void run() { try { //需要写入的文件 File file = new File("E:\\test\\c.txt"); file.createNewFile(); //处理流 输入 DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String fileName = dataInputStream.readUTF(); long fileSize = dataInputStream.readLong(); System.out.println("fileName=" + fileName + ",fileSize=" + fileSize); //处理流 输出 DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(file)); //采用字节数组读取文件内容 byte[] bytes = new byte[128]; int readSize = dataInputStream.read(bytes, 0, bytes.length); System.out.println("readSize=" + readSize); while (readSize != -1) { //写入本地文件 dataOutputStream.write(bytes, 0, readSize); dataOutputStream.flush(); readSize = dataInputStream.read(bytes, 0, bytes.length); System.out.println("readSize=" + readSize); } System.out.println("========文件上传完成=========="); } catch (Exception e) { e.printStackTrace(); } } }
服务端
package com.wfd360.com.socketFile; import com.wfd360.com.socketFile.thread.HandleServerThread; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * @Copyright (C) 四川千行你我科技有限公司 * @Author: LI DONG PING * @Date: 2019-09-01 15:14 * @Description: */ public class ServerSocketDemo { static int port = 1103; /** * 服务端开启多线程 * * @param args */ public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(port); int i=1; System.out.println("服务端已启动----"+i); while (true) { System.out.println("等待客户端连接---"+i); Socket socket = server.accept(); System.out.println("已连接---"+i); HandleServerThread thread = new HandleServerThread(socket); thread.start(); i++; } } }
客户端
package com.wfd360.com.socketFile; import java.io.*; import java.net.Socket; /** * @Copyright (C) 四川千行你我科技有限公司 * @Author: LI DONG PING * @Date: 2019-09-01 15:50 * @Description: */ public class ClientSocketDemo { static String host = "192.168.0.103"; static Integer port = 1103; /** * 客户端设计逻辑: * 1.创建socket通信,设置IP和端口 * 2.建立IO输出流,向服务端发送数据 * 3.建立IO输入流,读取服务端应答的数据 * * @param args */ public static void main(String[] args) throws Exception { Socket socket = new Socket(host, port); //准备上传文件 File file = new File("E:\\test\\a.txt"); DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file)); //准备输出 处理流 DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF(file.getName()); dataOutputStream.flush(); dataOutputStream.writeLong(file.length()); dataOutputStream.flush(); //准备以字节的形式输出 byte[] bytes = new byte[128]; int readSize = dataInputStream.read(bytes, 0, bytes.length); while (readSize != -1) { System.out.println("readSize=" + readSize); dataOutputStream.write(bytes, 0, readSize); dataOutputStream.flush(); readSize = dataInputStream.read(bytes, 0, bytes.length); } System.out.println("-----完成-------"); dataInputStream.close(); //当关闭的时候,服务端才会停止监听 dataOutputStream.close(); } }
6.UDP的socket
服务端
package com.wfd360.com.socketUDP; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; public class UDPServer { /** * 一、DatagramPacket类: * * 如果把DatagramSocket比作创建的港口码头,那么DatagramPacket就是发送和接收数据的集装箱。 * 构造函数:一个用来接收数据,一个用来发送数据 * public DatagramPacket(byte[] buf,int length) //接收数据 * 构造 DatagramPacket 用来接收长度为 ilength 的包。 * public DatagramPacket(byte[] buf,int length,InetAddress address,int port) * 构造数据报文包用来把长度为 ilength 的包传送到指定宿主的指定的端口号。 * getAddress() * 返回接收或发送此数据报文的机器的 IP 地址。 * getData() * 返回接收的数据或发送出的数据。 * getLength() * 返回发送出的或接收到的数据的长度。 * getPort() * 返回接收或发送该数据报文的远程主机端口号。 * * 二、DatagramSocket类 * * 此类表示用来发送和接收数据报包的套接字。 数据报套接字是包投递服务的发送或接收点。 * DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。 * DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。 * * receive(DatagramPacket p) * 从此套接字接收数据报包。 * void send(DatagramPacket p) * 从此套接字发送数据报包。 * bind(SocketAddress addr) * 将此 DatagramSocket 绑定到特定的地址和端口。 * void close() * 关闭此数据报套接字。 * void connect(InetAddress address, int port) * 将套接字连接到此套接字的远程地址。 * void connect(SocketAddress addr) * 将此套接字连接到远程套接字地址(IP 地址 + 端口号)。 * void disconnect() * 断开套接字的连接。 * getInetAddress() * 返回此套接字连接的地址。 * InetAddress getLocalAddress() * 获取套接字绑定的本地地址。 * * 三、InetAddress类 * InetAddress用于表示计算机IP地址的一个类,而在日常应用中的IP地址用"192.168.0.1", * "WWW.it315.org"等字符串格式表示的。 * getByName方法 * getHostAddress方法 * @param args */ public static void main(String[] args) throws Exception { int port=1001; String host="192.168.0.103"; //1.创建服务端 DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。 DatagramSocket datagramSocket = new DatagramSocket(port); System.out.println("服务已开启-----"); //2.接收数据 byte[] bytes=new byte[128]; DatagramPacket datagramPacket =new DatagramPacket(bytes,0,bytes.length) ; System.out.println("-----等待接收数据"); datagramSocket.receive(datagramPacket); InetAddress address = datagramPacket.getAddress(); int port1 = datagramPacket.getPort(); int length = datagramPacket.getLength(); byte[] data = datagramPacket.getData(); String s = new String(data); String format = String.format("address=%s,port=%s,length=%s,data=%s", address, port1, length, s); System.out.println(format); //3.发送数据包 String sendData="发送数据-"+s; byte[] bytes1 = sendData.getBytes(); InetAddress byName = InetAddress.getByName(host); DatagramPacket datagramPacketSend =new DatagramPacket(bytes1,0,bytes1.length,byName,1002) ; datagramSocket.send(datagramPacketSend); } }
客户端
package com.wfd360.com.socketUDP; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; public class UDPClient { public static void main(String[] args) throws Exception { int port=1002; String host="192.168.0.103"; //1.创建服务端 DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。 DatagramSocket datagramSocket = new DatagramSocket(port); //3.发送数据包 String sendData="你好吗?"; byte[] bytes1 = sendData.getBytes(); InetAddress byName = InetAddress.getByName(host); DatagramPacket datagramPacketSend =new DatagramPacket(bytes1,0,bytes1.length,byName,1001) ; datagramSocket.send(datagramPacketSend); //2.接收数据 byte[] bytes=new byte[128]; DatagramPacket datagramPacket =new DatagramPacket(bytes,0,bytes.length) ; System.out.println("-----等待接收数据"); datagramSocket.receive(datagramPacket); InetAddress address = datagramPacket.getAddress(); int port1 = datagramPacket.getPort(); int length = datagramPacket.getLength(); byte[] data = datagramPacket.getData(); String s = new String(data); String format = String.format("address=%s,port=%s,length=%s,data=%s", address, port1, length, s); System.out.println(format); } }
完美!
以上是关于socket系统化入门的主要内容,如果未能解决你的问题,请参考以下文章