通常情况下我们都是通过web基于URL的方式来访问Internet上的资源,但是还有基于client/server(客户端/服务器)模式的应用以及实现某些特殊的协议的应用,它的通讯过程是基于TCP/IP协议中 传输层 接口 Socket 实现的,这里就简单介绍一下利用 Java 采用Socket来实现简单的数据交互。
Socket简介
Socket是两个程序之间进行双向数据传输的网络通讯端点,有一个地址和一个端口号来标识。每个服务程序在提供服务时都要在一个端口进行,而想使用该服务的 客户机 也必须连接该端口。Socket因为是基于传输层,所以它是比较原始的通讯协议机制。通过Socket的数据表现形式为字节流信息,因此通讯双方要想完成某项具体的应用则必须按双方约定的方式进行数据的格式化和解释,我们可以看出使用Socket编程比较麻烦,但是它具有更强的灵活性和更广泛的使用领域。
看一张图
服务器端:
InputStream ——输入流,是用来接收来自客户端的数据。
output Stream——-输出流,是服务器向客户端发送的数据。
客户端:
InputStream——输入流,是用来接收来自服务端的数据。
OutputStream——-输出流,是客户端向服务器端发送的数据。
下面我们就通过具体的代码来演示一下
Server端
- 首先调用ServerSocket类以某个端口号为参数,创建一个ServerSocket对象,即是服务器端的服务程序在该指定端口监听的Socket。
- 服务器端程序使用ServerSocket对象的 accept ()方法,接收来自客户机程序的连接请求,此时服务器端将一直保持停滞状态,直到收到客户端发来的连接请求,此时该方法将返回一个新建的Socket类的实例,代表和客户机建立的通讯链路在服务程序内的通讯端点。如果采用Java的多线程编程方法,可以实现并发服务器,继续监听来自其他客户的连接请求。
- 使用新建的Socket对象创建输入、输出流对象。
- 使用流对象的方法完成和客户端的数据传输,按约定协议识别并处理来自客户端的请求数据,并把处理的结果返回给客户端。
- 客户端工作完毕后,则服务器端程序关闭和客户端通讯的流和通讯的Socket。
- 在服务器程序运行结束之间,应当关闭用来监听的Socket.
- 下面来看看具体的代码实现
package socket; import java. io .BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; /** * socket 网络编程 服务端 * @author chengjian * @date 2019/7/16 */ public class SocketServer { /** * @param args */ public static void main(String[] args) throws Exception { //设置标志位为真 boolean flag=true; //创建Socket client以接收来自客户端的请求 Socket client=null; String inputLine; //以端口5000创建一个服务器Socket ServerSocket serverSocket =new ServerSocket (5000); System.out.println("服务器在端口5000上监听"); //也可以使用serverSocket.getLocalPort()来获得端口号 while(flag) { client=serverSocket.accept(); //监听并接受与此Socket的连接,该方法会阻塞直到有一个连接产生 DataInputStream input=new DataInputStream(new BufferedInputStream(client.getInputStream())); PrintStream output=new PrintStream(new BufferedOutputStream(client.getOutputStream())); while (( inputLine= input.readLine())!=null) { System.out.println("客户端传递内容:" + inputLine); if(inputLine.equals("quit")) { flag=false; break; } output.println(inputLine); output.flush(); } output. close (); input.close(); client.close(); } serverSocket.close(); } }
Client客户端
- 首先调用Socket类的构造函数,以服务器的指定的IP地址或指定的主机名和指定的端口号为参数,创建一个Socket流,在创建Socket流的过程中包含了向服务器请求建立通讯连接的过程实现。
- 建立了客户端通讯Socket后。就可以使用Socket的方法getInputStream()和getOutputStream()来创建输入/输出流。这样,使用Socket类后,网络输入输出也转化为使用流对象的过程。
- 使用输入输出流对象的相应方法读写字节流数据,因为流连接着通讯所用的Socket,Socket又是和服务器端建立连接的一个端点,因此数据将通过连接从服务器得到或发向服务器。这时我们就可以对字节流数据按客户端和服务器之间的协议进行处理,完成双方的通讯任务。
- 待通讯任务完毕后,我们用流对象的close()方法来关闭用于网络通讯的输入输出流,在用Socket对象的close()方法来关闭Socket。
下面我们来看看客户端代码
package socket;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
/**
* socket网络编程客户端
* @author chengjian
* @date 2019/7/16
*/
public class SocketClient {
public static void main(String[] args) {
try {
// 创建一个流Socket并与主机mice上的端口5000相连接
Socket clientSocket = new Socket(InetAddress.getByName("127.0.0.1"), 5000);
// 向此Socket写入字节的一个输出流
OutputStream output = clientSocket.getOutputStream();
DataInputStream input = new DataInputStream(clientSocket.getInputStream());
// 创建新的数据输入流以便从指定的输入流中读出数据
int c;
String response;
// 从屏幕上接受输入的 字符串 ,并且分解成一个个字符
while ((c = System.in.read()) != -1)
{
output.write((byte) c);
// 如果字符为回车,则输出字符串缓冲
if (c == '\n')
{
output.flush();
response = input.readLine();
System.out.println("数据交互相应:" + response);
}
}
output.close();
input.close();
clientSocket.close();
} catch (Exception e)
{
e.printStackTrace();
System.out.println("出现错误!");
}
}
}
这样我们就完成java采用Socket实现简单的网络编程,这两个类可以直接复制运行