Socket通讯——经典ECHO模型
当我们学完Socket时,总感觉Socket简单,一学就会,但是真正让我们写东西的时候却什么也写不出来,下面让我们来看看ECHO用Socket实现起来会是什么样子
先上代码
服务器端:
package com.thz.network;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 2018/2/26:通过不稳定的UDP连接与客户端建立稳定的TCP连接
* @author THZ
* @version 1.0
*/
public class TcpServer2 {
public static void main(String[] args) throws Exception {
//接收并验证用户口令
byte[] byt = new byte[1024];
DatagramSocket socketU = new DatagramSocket(9000);
DatagramPacket packetUs = new DatagramPacket(byt, 0, byt.length);
String command = "";
while (!"123456".equals(command)) {
socketU.receive(packetUs);
command = new String(byt, 0, packetUs.getLength());
}
//构建一个随机端口的TServerSocket对象
ServerSocket sSocket = new ServerSocket();
sSocket.bind(null);
//构造并发送端口
String port = "" + sSocket.getLocalPort();
DatagramPacket packetU = new DatagramPacket(port.getBytes(), port.length(), packetUs.getAddress(), packetUs.getPort());
socketU.send(packetU);
socketU.close();
//----------------------------
//建立连接并获取流对象
Socket socket = sSocket.accept();
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
//交互
while (true) {
int len = is.read(byt);
if (len == -1)
continue;
if ("exit".equals(new String(byt , 0, len))) {
socket.close();
sSocket.close();
break;
}
os.write(("Server:" +new String(byt, 0, len)).getBytes());
}
}
}
客户端:
package com.thz.network;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* 2018/2/26:客户端发送登录口令,经过服务器验证通过后与服务器建立TCP连接
* @author THZ
* @version 1.0
*/
public class TcpClient {
public static void main(String[] args) throws Exception {
//一·UDP部分
DatagramSocket socketU = new DatagramSocket();
//1.构造并发送登录口令
String command = "123456";
DatagramPacket packetUs = new DatagramPacket(command.getBytes(), command.length(), InetAddress.getByName("localhost"), 9000);
socketU.send(packetUs);
//2.接收服务器返回的TCP连接端口
byte[] byt = new byte[1024];
DatagramPacket packetU = new DatagramPacket(byt, 0, byt.length);
socketU.receive(packetU);
int port = Integer.parseInt(new String(byt, 0 , packetU.getLength()));
socketU.close();
//----------------------------------
//二·TCP部分
//1.建立连接并获取流对象
Socket socket = new Socket("localhost", port);
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
Scanner scanner = new Scanner(System.in);
//2.交互
while (true) {
String message = scanner.nextLine();
if ("exit".equals(message)) {
os.write(message.getBytes());
scanner.close();
socket.close();
break;
}
os.write(message.getBytes());
int len = is.read(byt);
System.out.println(new String(byt, 0, len));
}
}
}
项目简单描述:
对于此ECHO由于是网络通讯,所以我加了密令验证的部分,密令验证不需要稳定连接,所以使用UDP完成,密令验证不通过继续验证,通过后与客户端建立TCP连接,通讯开始,客户端发送什么服务器返回什么,直到遇到‘exit’为止,服务器客户端均关闭,通讯完成。
验证密令过程简单,所以我从后面建立TCP连接开始分析
当密令验证通过后服务器会绑定一个随机可用的端口(避免端口占用问题)sSocket.bind(null);
然后将此端口通过UDP发送给通过密令验证的客户端String port = "" + sSocket.getLocalPort();
DatagramPacket packetU = new DatagramPacket(port.getBytes(), port.length(), packetUs.getAddress(), packetUs.getPort());
socketU.send(packetU);
客户端接收并解析出 端口socketU.receive(packetU);
int port = Integer.parseInt(new String(byt, 0 , packetU.getLength()));
至此UDP部分结束,UDP关闭
服务器调用accept()方法等待客户端连接Socket socket = sSocket.accept();
客户端在以接收到的端口连接服务器Socket socket = new Socket("localhost", port);
服务器客户端取得IO流开始通讯
客户端发送‘exit’服务器结束通讯,TCP关闭
至此,整个项目结束,欢迎各位朋友留言指点,共同学习共同进步!!!