用socket实现客户端和服务端的通信 (java)

效果如下
这里写图片描述
首先我们要懂几个关键词
socket,InputStream,OutputStream,BufferReader
举个例子,假如两个人A,B要通信,他们使用一种信件交流的方法,并且规定好了信箱,一方把信件放在信箱里面,另一方就可以去看

socket简单来说就是连接两个程序的程序,就是信箱
在A程序中
InputStream 读入流,相当于是A写的信
OutputSream是A收到的信
BufferReader相当于是用上等的纸写的信~作为缓冲输入,他拥有比InputStream更高的效率

其次我们再了解一下地址的概念,不懂也不影响编程,记住就行

127.0.0.1是回送地址,指本地机,一般用来测试使用。回送地址是本机回送地址(Loopback Address),即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,协议软件立即返回,不进行任何网络传输。

8080是自己的电脑的端口号

好了接下来我们来看代码
首先我们要解决连接问题,我们来看这段程序

//用socket在本机实现连接
Socket socket=new Socket("127.0.0.1",8080);
//将socket在本机中获得的输入流和输出流赋给当前程序
DataInputStream inputStream=new DataInputStream(socket.getInputStream());
DataOutputStream outputStream=new DataOutputStream(socket.getOutputStream());
//额外定义输入流,System.in表示从控制台也就是console可以输入到bufferedReader中
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));

上面这段程序实现了连接,其次是两者通信的过程是怎样的?

接下来我们只需要写两个类,一个客户端一个服务端
他们的区别在于服务端加了行监听8080的代码,实现两端的通信,整个过程如图
这里写图片描述

既然是服务端监听客户端,那么服务端肯定是先执行,但是不能一下执行完,否则客户端无法连接,所以在打开监听端口后将会阻塞,使用accept()方法,同时应该放在子线程中,因为主线程中最好不要出现阻塞

//创建监听端口
ServerSocket serverSocket = new ServerSocket(8080);
//阻塞
Socket socket=serverSocket.accept();

最后一点是如何执行通信?其中服务端的代码如下

	//读取信息要放在最前面,以读取客户端发来的信息
	String iString=inputStream.readUTF();
	System.out.println(iString);
	//从控制台读入信息
	String aString=bufferedReader.readLine();
	if(aString.equals("bye"))break;
	//写到输出流中,由于有了连接,客户端的读入流可以读到输出流中的内容			
	outputStream.writeUTF(aString);
	outputStream.flush();				

过程如下,两者的输入流和输出流是对应的

坑都解决完了,以下是源程序,现在应该很好理解了
服务端

package com.chat;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ChatServer{
	public static void main(String [] args) throws EOFException {
		System.out.println("服务器运行...");
		Thread thread=new Thread(()->{//这是lambda表达式,写在线程方法中非常方便
			
			try (
				ServerSocket serverSocket = new ServerSocket(8080);
				Socket socket=serverSocket.accept();
				
				DataInputStream inputStream=new DataInputStream(socket.getInputStream());
				DataOutputStream outputStream=new DataOutputStream(socket.getOutputStream());
				BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
				){	
				while(true) {
					String iString=inputStream.readUTF();//读取信息要放在最前面,以读取客户端发来的信息
					System.out.println(iString);
					String aString=bufferedReader.readLine();
					if(aString.equals("bye"))break;
				
					//写入输出流
					outputStream.writeUTF(aString);
					//将输出流刷新
					outputStream.flush();
					
					
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("服务器停止");
		});
		thread.start();
	}
}

客户端

package com.chat;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;

public class ChatClient{
	public static void main(String [] args) throws EOFException{
		System.out.println("客户端启动...");
		Thread thread=new Thread(()->{
			try (
				Socket socket=new Socket("127.0.0.1",8080);
				DataInputStream inputStream=new DataInputStream(socket.getInputStream());
				DataOutputStream outputStream=new DataOutputStream(socket.getOutputStream());
				BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
				){
				while(true) {
					String aString=bufferedReader.readLine();
					if(aString.equals("bye"))break;
					outputStream.writeUTF(aString);
					outputStream.flush();
					
					String iString=inputStream.readUTF();
					System.out.println(iString);
				}
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
			} 
			catch (ConnectException e) {
				System.out.println("服务器未启动!");
				}catch (IOException e) {//必须放在所有的catch的最后
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("客户端停止");
		});
		thread.start();
	}
}
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页