Java版:一个极致精简的socket通讯服务器和客户端
来源:程序猿的内心独白(头条)https://p1-tt.byteimg.com/origin/pgc-image/2f61b09a771b49e4b9de11ce4e74a427?from=pc
什么是socket网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。TCP/IP UDP是什么?TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。下面是他们三者的关系:https://p6-tt.byteimg.com/origin/pgc-image/cba6964ac11b48139aeb336da35532d1?from=pc
可以看出TCP/IP协议族包括运输层、网络层、链路层。socket是一个接口,在用户进程与TCP/IP协议之间充当中间人,完成TCP/IP协议的书写,用户只需理解接口即可。https://p6-tt.byteimg.com/origin/pgc-image/d16906207af84a5fbac90d28c1fda5a3?from=pc
所以socket到底是什么?Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。https://p1-tt.byteimg.com/origin/pgc-image/679e6afb591c4a0bb037e2c5dd6f8444?from=pc
socket工作原理要通过互联网进行通信,至少需要一对套接字,一个运行于客户机端,称之为ClientSocket,另一个运行于服务器端,称之为serverSockethttps://p6-tt.byteimg.com/origin/pgc-image/1a6f49361361469aaa581c3e2efd05bd?from=pcsocket工作原理
socket服务器和客户端源码服务器代码:import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.ServerSocket;import java.net.Socket;public class Server {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(2000);System.out.println("服务器准备就绪");//System.out.println("client: "+ socket.getLocalAddress() + " p : " + socket.getLocalPort());System.out.println("服务器信息 : " + serverSocket.getInetAddress() + " p : " + serverSocket.getLocalPort());//等待客户端连接while (true) {Socket client = serverSocket.accept();ClientHandler clientHandler = new ClientHandler(client);clientHandler.start();}}private static class ClientHandler extends Thread{private Socket socket;ClientHandler(Socket socket){this.socket = socket;}private boolean flag = true;@Overridepublic void run() {//super.run();System.out.println("新客户端连接: " + socket.getInetAddress() + "p: " + socket.getPort());try {//得到打印流,用于数据输出;服务器回送数据使用PrintStream soketOutput = new PrintStream(socket.getOutputStream());//得到输入流,用于接收数据BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));do {//客户端拿到一条数据String str = socketInput.readLine();//String echo = socketInput.readLine();if ("bye".equalsIgnoreCase(str)) {flag = false;soketOutput.println("bye");}else {//打印到屏幕,并回送数据长度System.out.println(str);soketOutput.println("回送: " + str.length());}}while (flag);socketInput.close();soketOutput.close();} catch (IOException e) {System.out.println("连接异常断开");}finally {//连接关闭try {socket.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("客户端已退出: " + socket.getInetAddress() + " p : " + socket.getPort());}}}客户端代码:import java.io.*;import java.net.Inet4Address;import java.net.InetSocketAddress;import java.net.Socket;public class Client {public static void main(String[] args) throws IOException {Socket socket = new Socket();socket.setSoTimeout(3000);//连接本地,端口2000;超时时间为3000mssocket.connect(new InetSocketAddress(Inet4Address.getLocalHost(),2000), 3000);System.out.println("服务器已连接");System.out.println("client: "+ socket.getLocalAddress() + " p : " + socket.getLocalPort());System.out.println("服务器信息 : " + socket.getInetAddress() + " p : " + socket.getPort());try {todo(socket);}catch (Exception e){System.out.println("关闭异常");}socket.close();System.out.println("客户端已退出");}private static void todo(Socket client) throws IOException{InputStream in = System.in;BufferedReader input = new BufferedReader(new InputStreamReader(in));//得到soket输出流,并转换为打印流OutputStream outputStream = client.getOutputStream();PrintStream sockePrintStream = new PrintStream(outputStream);// 得到sokcet输入流,并转换为socketBufferReaderInputStream inputStream = client.getInputStream();BufferedReader sokcetBufferedReader = new BufferedReader(new InputStreamReader(inputStream));boolean flag = true;do {//键盘读取一行String str = input.readLine();//发送到服务器sockePrintStream.println(str);//从服务器读取一行String echo = sokcetBufferedReader.readLine();if ("bye".equalsIgnoreCase(echo)) {flag = false;}else {System.out.println(echo);}}while (flag);//关闭socket流sockePrintStream.close();sokcetBufferedReader.close();}}执行效果:https://p3-tt.byteimg.com/origin/pgc-image/88d87715e4554d66af64b339c0714d7d?from=pc
https://p3-tt.byteimg.com/origin/pgc-image/be9ea76045634450a53ec013da2a7dc2?from=pc
socket总结根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客 户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。https://p3-tt.byteimg.com/origin/pgc-image/bd000c9861cb43fe84bf8fd8b707c886?from=pc
无私奉献,好工控人,32个赞送给你!! 我顶,我顶,我顶顶顶 说得对!狠狠赞同,没毛病~ 水个经验,支持楼主,加油呀 路过混个脸熟,顺便为优质内容打 call~ 我先占个楼,等下再慢慢看~ 内容太顶了!疯狂点赞,已默默收藏~ 同款经历!我当初也这么过来的😂 楼主辛苦啦,期待下一篇分享
页:
[1]
2