Java版:一个极致精简的socket通讯服务器和客户端

Java版:一个极致精简的socket通讯服务器和客户端

什么是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协议族中的一种。

下面是他们三者的关系:

Java版:一个极致精简的socket通讯服务器和客户端

可以看出TCP/IP协议族包括运输层、网络层、链路层。socket是一个接口,在用户进程与TCP/IP协议之间充当中间人,完成TCP/IP协议的书写,用户只需理解接口即可。

Java版:一个极致精简的socket通讯服务器和客户端

所以socket到底是什么?

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

Java版:一个极致精简的socket通讯服务器和客户端

socket工作原理

要通过互联网进行通信,至少需要一对套接字,一个运行于客户机端,称之为ClientSocket,另一个运行于服务器端,称之为serverSocket

Java版:一个极致精简的socket通讯服务器和客户端

socket工作原理

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;

@Override

public 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;超时时间为3000ms

socket.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输入流,并转换为socketBufferReader

InputStream 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();

}

}

执行效果:

Java版:一个极致精简的socket通讯服务器和客户端

Java版:一个极致精简的socket通讯服务器和客户端

socket总结

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认

服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客 户端,一旦客户端确认了此描述,连接就建立好了。

而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

Java版:一个极致精简的socket通讯服务器和客户端

相关推荐