TCP链接简介
TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立通过三次握手,释放则需要四次握手,所以说每个连接的建立都是需要资源消耗和时间消耗的。
长连接
模拟一种长连接的情况:
- client 向 server 发起连接
- server 接到请求,双方建立连接
- client 向 server 发送消息
- server 回应 client
- 一次读写完成,连接不关闭
- 后续读写操作…
- 长时间操作之后client发起关闭请求
长连接的操作步骤是:
建立连接——数据传输…(保持连接)…数据传输——关闭连接
服务器
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;
public class TCPTransport {
private static final int SERVER_PORT=8883;
private static Hashtable<String, Socket> ht = new Hashtable();
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("VNTCenter.main()===TCP SERVER==============");
//新建
ServerSocket vntServer = null;
try{
//监听本机的端口的地址是否有链接
vntServer= new ServerSocket(SERVER_PORT);
System.out.println("监听的端口 "+vntServer.getLocalPort()+"...");
while(true){
//在服务端调用accept()方法接受客户端的连接对象
Socket vntClient=vntServer.accept();
System.out.println("客户IP "+vntClient.getInetAddress()+"...");
System.out.println("客户端口 "+vntClient.getPort()+"...");
//新建线程
new GetGpsThreadFun(vntClient).start();
//进客户端ip转为String字符串,存到map中
ht.put(vntClient.getInetAddress().toString(),vntClient);
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
vntServer.close();
}
}
}
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class GetGpsThreadFun extends Thread{
private Socket vntThreadClient;
public GetGpsThreadFun(Socket vntThreadSocket){
vntThreadClient=vntThreadSocket;
}
public void run(){
try{
//显示时间
Date day=new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(day));
byte[] data = new byte[1024];
while(true){
int len = vntThreadClient.getInputStream().read(data);
if (len > 0){
//打印客户端IP:端口:接收的数据(字符串的转化方法)
System.out.println(vntThreadClient.getInetAddress()+":"+vntThreadClient.getPort()+":"+new String(data,0,len));
//给客户端返回TCP
vntThreadClient.getOutputStream().write("TCP".getBytes());
if("shutdown".equals(vntThreadClient)){
//停止本次循环
break;
}
}
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
短链接
模拟一种TCP短连接的情况:
- client 向 server 发起连接请求
- server 接到请求,双方建立连接
- client 向 server 发送消息
- server 回应 client
- 一次读写完成,此时双方任何一个都可以发起 close 操作
短连接的操作步骤是:
建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接
服务器
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
public class TCPThreadServer {
private static final int PORT = 8883;
public static void main(String[] args) {
int count = 1;
try {
/**
* 创建一个ServerSocket对象,并给它制定一个端口号,
* 通过这个端口号来监听客户端的连接,服务端接受客户端连接的请求是
* 不间断地接受的,所以服务端的编程一般都永无休止的运行
*/
ServerSocket ss = new ServerSocket(PORT);
System.out.println("服务器已经启动。。。");
while (true) {
/**
* 在服务端调用accept()方法接受客户端的连接对象,accept()方法是
* 一个阻塞式的方法,一直傻傻地等待着是否有客户端申请连接
*/
Socket s = ss.accept();
System.out.println("共" + count + "次链接");
System.out.println("现连接IP地址是:"+s.getInetAddress());
count++;
/** 获取当前的系统时间,与初始时间相减就是程序运行的毫秒数,除以1000就是秒数*/
/**
* 服务端使用多线程方便多客户端的连接
* 这里将服务端的socket传给内部类,方便每个客户端都创建一个线程
*/
Thread t = new Thread(new TCPThreadServerSocket(s));
t.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
class TCPThreadServerSocket implements Runnable {
private Socket socket = null;
private InputStream in = null;
private OutputStream out = null;
public TCPThreadServerSocket(Socket s) {
this.socket = s;
}
@Override
public void run() {
try {
//获取服务端输入的消息
in = socket.getInputStream();
//显示时间
Date day=new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(day));
//服务端返回的消息
out = socket.getOutputStream();
//用一个字节数字来存放消息,提高效率
byte[] recData = new byte[1024];
int length = in.read(recData);
String hc = new String(recData, 0, length);
System.out.println("读取到客户端发送来的数据:" + hc);
//返回给客户端的消息
out.write("REG".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//关闭资源
in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Test {
public static void main(String[] args) throws IOException {
// 建立tcp服务
Socket socket = new Socket(InetAddress.getLocalHost(), 8883);
//Socket socket = new Socket("120.53.236.19", 8883);
// 获取socket输出流对象
OutputStream outputStream = socket.getOutputStream();
// 写数据
String data = "HY:456,-123,000";
outputStream.write(data.getBytes());
// 与服务器端交互
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = inputStream.read(buf);
System.out.println("客户端收到" + new String(buf, 0, length));
// 关闭资源
socket.close();
}
}