用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();
	}
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
01-15 20:52
黑皮白袜臭脚体育生:五宿大战是吧,死去的记忆还在攻击我
点赞 评论 收藏
分享
01-28 16:12
中南大学 Java
几年前还没有chatgpt的时候,刷题真的是很痛苦。刷不出来只能看题解,题解有几个问题:第一个是每次看的写题解的人都不一样,很难有一个统一的思路;第二个也是最重要的是,题解只提供了作者自己的思路,但是没有办法告诉你你的思路哪里错了。其实很少有错误的思路,我只是需要被引导到正确的思路上面去。所以传统题解学习起来非常困难,每次做不出来难受,找题解更难受。但是现在chatgpt能做很多!它可以这样帮助你 -1. 可以直接按照你喜欢的语言生成各种解法的题解和分析复杂度。2. 把题和你写的代码都发给它,它可以告诉你 你的思路到底哪里有问题。有时候我发现我和题解非常接近,只是有一点点🤏想错了。只要改这一点点就是最优解。信心倍增。3. 如果遇到不懂的题解可以一行一行询问为什么要这样写,chatgpt不会嫌你烦。有时候我觉得自己的range写错了,其实那样写也没错,只是chat老师的题解有一点优化,这个它都会讲清楚。4. 它可以帮你找可以用同类型解法来做的题。然后它可以保持解法思路不变,用一个思路爽刷一个类型的题。如果题目之间思路又有变化,它会告诉你只有哪里变了,其他的地方还是老思路。5. 它也可以直接帮你总结模板,易错点。经过chat老师的指导,我最大的改变是敢刷题了。之前刷题需要先找某一个人写的算法题repo,然后跟着某一个人他的思路刷他给的几个题。如果想写别的题,套用思路失败了,没有他的题解,也不知道到底哪里错了;看别人的题解,思路又乱了。这个问题在二分查找和dp类型的题里面特别常见。但是现在有chat老师,他会针对我的代码告诉我我哪里想错了,应该怎么做;还按照我写代码的习惯帮我总结了一套属于我的刷题模板。每天写题全是正反馈!
牛客981:不刷才是爽
AI时代的工作 VS 传...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务