目录
socket简介
socket是基于TCP/IP网络层的一种传输方式
首先,服务端初始化ServerSocket,然后对指定的端口进行绑定,接着对端口及进行监听,通过调用accept方法阻塞,此时,如果客户端有一个socket连接到服务端,那么服务端通过监听和accept方法可以与客户端进行连接。
多线程下socket
每一个客户端都可以连接到服务端,并且实时发送消息;服务端采用多线程的模式运行,每一个客户端连接都专门创建一个线程进行处理
服务端
package com.jiajia;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerSocketTest {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9999);
ExecutorService executorService = Executors.newFixedThreadPool(100);
//这里相当于用accept进行阻塞,成为一个循环,每有一个客户端进行连接的时候,就分配一个线程进行处理
while (true) {
Socket accept = serverSocket.accept();
Runnable runnable =() -> {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream(),"utf-8"));
String s = null;
while ((s = bufferedReader.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
};
executorService.submit(runnable);
}
}
}
客户端
package com.jiajia;
import java.io.*;
import java.net.Socket;
public class ClientSocket2 {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",9999);
//字符输出流
BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())) ;
//字符输入流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, "utf-8"));
while (true) {
String s = bufferedReader.readLine();
bufferedWriter.write(s);
bufferedWriter.write("\n");
bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
实际应用的socket
由于上面使用的是默认缓冲区(8*1024个字节),如果数据过大就需要多次进行分包发送,分包就会导致半包、分包的状况出现,导致接受不全,所以最好一次分发完成(采用精确的缓冲池进行接受)!
所以采用以下形式:
固定长度:每次发送固定长度的数据;
特殊标示:以回车,换行作为特殊标示;获取到指定的标识时,说明包获取完整。
字节长度:包头+包长+包体的协议形式,当服务器端获取到指定的包长时才说明获取完整;
方法:包类型+包长度+消息内容定义一个socket通信对象,数据类型为byte类型,包长度为int类型,消息内容为byte类型。
服务端
package com.jiajia;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerSocketTest2 {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9999);
ExecutorService executorService = Executors.newFixedThreadPool(100);
//这里相当于用accept进行阻塞,成为一个循环,每有一个客户端进行连接的时候,就分配一个线程进行处理
while (true) {
Socket accept = serverSocket.accept();
Runnable runnable = () -> {
try {
DataInputStream dataInputStream = new DataInputStream(accept.getInputStream());
String s = null;
while (true) {
byte b = dataInputStream.readByte();
int i = dataInputStream.readInt();
//byte占1个字节,int占4个字节 缓冲池的大小为 i-5
byte[] data = new byte[i - 5];
dataInputStream.readFully(data);
String str = new String(data);
System.out.println("获取的数据类型为" + b);
System.out.println("获取的数据长度为" + i);
System.out.println("获取的数据内容为" + str);
}
} catch (Exception e) {
e.printStackTrace();
}
};
executorService.submit(runnable);
}
}
}
客户端
package com.jiajia;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class ClientSocket3 {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 9999);
//字符输出流
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
//字符输入流
Scanner scanner = new Scanner(System.in);
while (true) {
if (scanner.hasNext()) {
String str = scanner.next();
int type = 1;
byte[] bytes = str.getBytes();
int len = bytes.length + 5;
dataOutputStream.writeByte(type);
dataOutputStream.writeInt(len);
dataOutputStream.write(bytes);
dataOutputStream.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}