友情提示:SocketServer是服务端,SocketClient是客户端,先运行服务端再运行客户端,在客户端输入信息可在服务端返回,实现最简单的交互服务。另注意导包问题。
While 实现
socket 编程 C/S 结构
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 客户端
*/
public class SocketClient {
public static void main(String[] args) {
try {
//初始化一个socket
Socket socket = new Socket("127.0.0.1", 9999);
//通过socket获取字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//通过标准输入流获取字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
while (true) {
String str = bufferedReader.readLine();
bufferedWriter.write(str);
bufferedWriter.write("\n");
bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 服务端,while循环连续接受客户端信息
*/
public class SocketServer {
public static void main(String[] args) {
try {
//初始化服务端socket并且绑定9999端口
ServerSocket serverSocket = new ServerSocket(9999);
//等待客户端的连接
Socket socket = serverSocket.accept();
//获取输入流,并且指定统一的编码格式
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
//读取一行数据
String str;
//通过while循环不断读取信息,
while ((str = bufferedReader.readLine()) != null) {
//输出打印
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果你想拓展,可以看看下面的多线程实现
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class SocketClient1 {
public static void main(String[] args) {
try {
//初始化一个socket
Socket socket = new Socket("127.0.0.1", 9999);
//通过socket获取字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//通过标准输入流获取字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
while (true) {
String str = bufferedReader.readLine();
bufferedWriter.write(str);
bufferedWriter.write("\n");
bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 多线程下 socket 服务端
*
* @author NNroc
* @date 2020/6/15 15:31
*/
public class SocketServer1 {
public static void main(String[] args) throws IOException {
//初始化服务端socket并且绑定9999端口
ServerSocket serverSocket = new ServerSocket(9999);
while (true) {
//等待客户端的连接
Socket socket = serverSocket.accept();
//每当有一个客户端连接进来后,就启动一个单独的线程进行处理
new Thread(new Runnable() {
@Override
public void run() {
//获取输入流,并且指定统一的编码格式
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
//读取一行数据
String str;
//通过while循环不断读取信息
while ((str = bufferedReader.readLine()) != null) {
//输出打印
System.out.println("客户端" + str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
线程
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 多线程下 socket 服务端
* 对于大量数据来说,当线程创建出来后未回收,会大量占用资源
*
* @author NNroc
* @date 2020/6/15 15:31
*/
public class SocketServer1 {
public static void main(String[] args) throws IOException {
//初始化服务端socket并且绑定9999端口
ServerSocket serverSocket = new ServerSocket(9999);
while (true) {
//等待客户端的连接
Socket socket = serverSocket.accept();
//每当有一个客户端连接进来后,就启动一个单独的线程进行处理
new Thread(new Runnable() {
@Override
public void run() {
//获取输入流,并且指定统一的编码格式
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
//读取一行数据
String str;
//通过while循环不断读取信息
while ((str = bufferedReader.readLine()) != null) {
//输出打印
System.out.println("客户端" + str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
线程池
服务端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 线程池下 socket 服务端,保证线程的复用
*
* @author NNroc
* @date 2020/6/15 15:46
*/
public class SocketServer2 {
public static void main(String[] args) throws IOException {
//初始化服务端socket并且绑定9999端口
ServerSocket serverSocket = new ServerSocket(9999);
//创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(100);
while (true) {
//等待客户端的连接
Socket socket = serverSocket.accept();
Runnable runnable = () -> {
SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
//读取一行数据
String str;
//通过while循环不断读取信息
while ((str = bufferedReader.readLine()).length() != 0) {
//输出打印
System.out.println("客户端" + remoteSocketAddress.toString() + "发送:" + str);
}
} catch (SocketException e) {
System.out.println("客户端" + remoteSocketAddress.toString() + "断开连接");
} catch (IOException e) {
e.printStackTrace();
}
};
executorService.submit(runnable);
}
}
}
客户端
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* @author NNroc
* @date 2020/6/15 15:35
*/
public class SocketClient1 {
public static void main(String[] args) {
try {
//初始化一个socket
Socket socket = new Socket("127.0.0.1", 9999);
//通过socket获取字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//通过标准输入流获取字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
while (true) {
String str = bufferedReader.readLine();
if (str.equals("end")) {
break;
}
bufferedWriter.write(str);
bufferedWriter.write("\n");
bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
设置需求
服务端
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* socket 指定长度发送数据
* 在不定长通讯中,通常使用的方式时每次默认读取 8*1024长度的字节,若输入流中仍有数据,则再次读取,一直到输入流没有数据为止。
* 但是如果发送数据过大时,发送方会对数据进行分包发送,这种情况下或导致接收方判断错误,误以为数据传输完成,因而接收不全。
* 在这种情况下就会引出一些问题,诸如半包,粘包,分包等问题,
*
* @author NNroc
* @date 2020/6/15 16:01
*/
public class SocketServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(9999);
Socket client = serverSocket.accept();
InputStream inputStream = client.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
while (true) {
byte b = dataInputStream.readByte();
int len = dataInputStream.readInt();
byte[] data = new byte[len - 5];
dataInputStream.readFully(data);
String str = new String(data);
System.out.println("获取的数据类型为:" + b);
System.out.println("获取的数据长度为:" + len);
System.out.println("获取的数据内容为:" + str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
/**
* @author NNroc
* @date 2020/6/15 16:09
*/
public class SocketClient1 {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 9999);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
Scanner scanner = new Scanner(System.in);
if (scanner.hasNext()) {
String str = scanner.next();
int type = 1;
byte[] data = str.getBytes();
int len = data.length + 5;
dataOutputStream.writeByte(type);
dataOutputStream.writeInt(len);
dataOutputStream.write(data);
dataOutputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}