创建一个客户端:
package Socket;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/*
聊天案例客户端
*/
public class Client {
private Socket socket;
/*
* 构造方法用于初始化客户端
* */
public Client() {
try {
/*
* 实例化Socket时需要指定两个信息
* 1、服务端Ip地址,如果链接的是本机,则使用localhost即可
* 2、服务端口,用来找到运行在服务端计算机上的服务端应用程序
*
* 实例化Socket的过程就是与服务端建立连接的过程,如果链接失败
* 则会抛出异常
* */
System.out.println("正在链接服务端。。。");
socket= new Socket("localhost",8088);
System.out.println("与服务端建立链接成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 客户端开始工作的方法
* */
public void start(){
try {
/*
Socket提供的重要方法:
OutputStream getOutputStream()
* 该方法用于获取一个字节输出流,用于向服务端发送数据
* */
OutputStream outputStream=socket.getOutputStream();
/*//向服务端发送一个字节数据:00000001
outputStream.write(1);*/
while (true){
System.out.println("输入要发送的内容:");
Scanner scan=new Scanner(System.in);
String str= scan.nextLine();
if ("exit".equalsIgnoreCase(str)){
break;
}
//用字符串表示发送的内容
//String str="你能学会java吗?";
//将字符串转换成字节数组
byte[] data=str.getBytes(StandardCharsets.UTF_8);
//先给服务端发送字节数组的字节数量,也就是要发送多少字节
outputStream.write(data.length);
//在将字符串转换的所有字节发送给服务端
outputStream.write(data);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
/*
* 当通讯完毕时,希望与对方断开链接应当调用close方法
* 1、close方法会关闭字节输入流和字节输出流
* 2、与对方进行四次挥手
* */
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Client client=new Client();
client.start();
}
}
创建一个服务端:
package Socket;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 聊天程序服务端
* */
public class Server {
/*
*运行在服务端的ServerSocket
* 主要工作:
* 1、向系统申请服务端口
* 2、监听该端口,一旦客户端通过该端口尝试链接则创建Socket与客户端建立链接
*/
private ServerSocket serverSocket;
private ExecutorService threadPool;
/*
* 构造方法
* */
public Server(){
try {
System.out.println("正在启动!");
serverSocket=new ServerSocket(8088);
threadPool= Executors.newFixedThreadPool(20);
System.out.println("启动完成");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
/*
* accept: 接受
*
* ServerSocket提供的方法:accept用于接受客户端的链接
该方法是一个阻塞方法,调用后程序"卡主",开始等待客户端的链接,一旦一个客户端
链接,该方法会立即返回一个Socket对象用于与该客户端进行数据交互。
* */
try {
while (true){
System.out.println("等待客户端链接");
Socket socket = serverSocket.accept();
System.out.println("一个客户端已连接");
//启动一个线程来处理该客户端交互
ClientHandler handler=new ClientHandler(socket);
/* Thread t=new Thread(handler);
t.start();*/
threadPool.execute(handler);
}
} catch(IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server=new Server();
server.start();
}
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket=socket;
}
public void run(){
/*
* Socket提供的额方法:
* InputStream getInputStream()
* 获取该Socket的输入流,用于读取对方发送的信息
* */
try {
InputStream inputStream = socket.getInputStream();
//读一个字节,得知客户端后续发送了多少个字节
int len;
/*
* 通过网络流读取对方发送过来的一个字节数据时
* 如果返回值为-1仍然是表达流读取到了末尾,此时只有当客户端正常断开
* 链接(进行了四次挥手时)read读到了-1
* */
while ((len=inputStream.read())!=-1) {
//创建字节数组,存储客户端发送的字节
byte[] data = new byte[len];
//读数据
inputStream.read(data);
//将数据转换成字符串
String message = new String(data, StandardCharsets.UTF_8);
System.out.println("客户端内容:" + message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}