用socke实现客户端和服务端的通信 (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();
}
}