注意:先启动服务端,再运行客户端
Client.java 客户端
package sdut.ligong.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
/**
* 1001 建立连接请求
*
* 1002 确认请求 1003 开始发送信息
*
* 1004 断开连接请求
*
* @author Lenovo
*
*/
public class Client1 {
/**
* 参考TCP报文首部格式
*
* 1.源端口和目的端口 各 占2个字节 2序号 占 4 字节 3确认号 占4字节 4数据偏移 占4位 5保留 占6位 6紧急 URG
* 为1表示紧急指针字段有效 7确认 ACK 为1表示有效 8推送 PSH 9复位RST 10同步SYN 11终止FIN 12窗口 13检验和
* 14紧急指针 15选项
*/
// 自定义报文首部格式为 确认号+报文长度+尾部(占一个字节,用于标注存储报文长度的位数)
public static int ESTABLISH_CONNECTION = 1001; // 建立连接
public static int CONFIRM_CONNECTION = 1002; // 确认连接
public static int SEND_INFORMATION = 1003; // 发送报文
public static int TERMINATE_CONNECTION = 1004; // 关闭连接
public static int MESSAGE_LENGTH = 0; // 发送信息的长度
public static int LengthBit = 0;//长度位数
private static String content = null;
public static void main(String[] args) throws IOException {
// 客户端请求与本机在20006端口建立TCP连接
Socket client = new Socket("127.0.0.1", 20006);
client.setSoTimeout(10000);
// 获取键盘输入
BufferedReader input = new BufferedReader(new InputStreamReader(
System.in));
// 获取Socket的输出流,用来发送数据到服务端
PrintStream out = new PrintStream(client.getOutputStream());
// 获取Socket的输入流,用来接收从服务端发送过来的数据
BufferedReader buf = new BufferedReader(new InputStreamReader(
client.getInputStream()));
boolean flag = true;
while (flag) {
System.out.print("请输入信息:");
content = input.readLine();
System.out.println("content is the "+content);
System.out.println("开始发送连接请求");
MESSAGE_LENGTH = 6;
// 发送1001 请求连接
out.println(ESTABLISH_CONNECTION + "" + MESSAGE_LENGTH+""+1);
// 发送数据到服务端
if ("bye".equals(content)) {
flag = false;
} else {
try {
// 从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常
String echo = buf.readLine();
if (echo.contains("1002")) {
System.out.println("请求被确认");
System.out.println("准备发送信息!");
MESSAGE_LENGTH = 4 + content.length() + 1;
int m = MESSAGE_LENGTH;
if(m+1==10){ //如果输入内容长度为4加上固定长度5,加上长度空间占位1,则报文总长度为10,长度空间需要再增一位
m=10;
}
boolean t = true;
LengthBit = 0;
while(t){
if(m==0){
t = false;
}else {
m=m/10;
LengthBit++;
}
}
MESSAGE_LENGTH+=LengthBit;//加上报文长度占的内存空间
//发送报文
out.println(SEND_INFORMATION +""+MESSAGE_LENGTH +""+content+""+LengthBit);
String echo2 = buf.readLine();
//解析报文
int num = Integer.parseInt(echo2.substring(echo2.length()-1));
System.out.println(echo2.substring(4+num, echo2.length()-1));
System.out.println(echo2);
} else {
System.out.println("请求连接被拒绝");
}
} catch (SocketTimeoutException e) {
System.out.println("超时,无响应");
}
}
}
input.close();
if (client != null) {
// 如果构造函数建立起了连接,则关闭套接字,如果没有建立起连接,自然不用关闭
client.close(); // 只关闭socket,其关联的输入输出流也会被关闭
}
}
}
Server1.java
package sdut.ligong.demo;
import java.net.ServerSocket;
import java.net.Socket;
public class Server1 {
public static void main(String[] args) throws Exception{
//服务端在20006端口监听客户端请求的TCP连接
ServerSocket server = new ServerSocket(20006);
Socket client = null;
boolean f = true;
while(f){
//等待客户端的连接,如果没有获取连接
client = server.accept();
System.out.println("与客户端连接成功!");
//为每个客户端连接开启一个线程
new Thread(new ServerThread(client)).start();
}
server.close();
}
}
ServerThread.java
package sdut.ligong.demo;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class ServerThread implements Runnable {
private Socket client = null;
public ServerThread(Socket client){
this.client = client;
}
@Override
public void run() {
try{
//获取Socket的输出流,用来向客户端发送数据
PrintStream out = new PrintStream(client.getOutputStream());
//获取Socket的输入流,用来接收从客户端发送过来的数据
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
boolean flag =true;
while(flag){
//接收从客户端发送过来的数据
String str = buf.readLine();
if(str == null || "".equals(str)){
flag = false;
}else{
if("bye".equals(str)){
flag = false;
}else{
//将接收到的字符串前面加上echo,发送到对应的客户端
if (str.contains("1001")&& (str.charAt(4)+"").equals(str.length()+"")) {//接收到请求连接
out.println("1002");
}else{
int endStart = Integer.parseInt(str.substring(str.length()-1));
if (str.contains("1003") && str.length()==Integer.parseInt(str.substring(4,4+endStart))) {
StringBuffer sb = new StringBuffer(str);
out.println(new String(sb.insert(4+endStart, "服务器端回应")));
} else {
out.print("请求失败");
}
}
}
}
}
out.close();
client.close();
}catch(Exception e){
e.printStackTrace();
}
}
}