记录自己的一次作业过程,用java实现客户机和服务器(有界面),并通过服务器给客户端发送一个验证码。用户输入验证码并判断是否正确。
一开始的想法是可以利用cmd给局域网下的其他设备发送一条信息,然后java调用相关的cmd命令。找到的两种方法有:
- MSG /server: IP地址 * 消息内容
- net send 计算机名/IP地址 “消息内容”
可是网上找到的一些例子都是很久以前的了,现在win10貌似已经已经不支持这两条命令了。如图:
经过很多次尝试后都没有达到我想要的效果。于是我决定换一种方法:分别写一个客户机和一个服务器,服务器创建端口后,用客户机连接。
服务器要想和客户机相连,就必须建立一对socket(套接字),套接字是通信协议的接口。
/*建立服务器:*/
ServerSocket server = new ServerSocket(port); //用port为端口号建立一个服务器
Socket socket = server.accept();//定义一个中介接收对象socket,此时服务器挂起,等待客户机连接
/*建立客户机:*/
InetAddress addr = InetAddress.getLocalHost();//获得本地的ip地址,要在两台设备上通信的话需要换成服务器的ip地址
Socket socket = new Socket(addr,port);//socket通过ip地址和端口号连接对应的服务器
要在两台设备上通信的话需要在new Socket()时将参数换成你所要连接的服务器的ip地址和端口号。并在连接前在那台设备上建立相应的服务器。
改:经实验后发现这样的连接在非局域网联机中不成功;换成局域网后成功。
这样连接就建立了,要想通信,还需要定义一个输入流和输出流(客户机和服务器都需要):
/*定义*/
BufferedReader input;
PrintStream output;
/*获取*/
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output= new PrintStream(socket.getOutputStream());
也有其他的输入输出流比如InputStream和OutputStream,不过我试过之后感觉他们的方法并不是很方便,感兴趣的朋友可以去了解一下各种输入输出流之间的区别。
我做的通信比较简单,在这里贴一下客户机和服务器的代码(还有两个界面的代码是添加按钮,分别调用客户机和服务器的创建方法)。
/*客户机*/
import java.awt.Color;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class client {
/*定义输入输出流*/
BufferedReader input;
PrintStream output;
Socket socket;
String code;
public static String s_code;
int flag;
File verify ;
JTextArea jt;//通过JTextArea显示对话
public client() {
// TODO Auto-generated constructor stub
/*文本区域,显示信息*/
jt = new JTextArea();
jt.setBounds(100,50,250,200);
jt.setBackground(Color.lightGray);
jt.setEditable(false);
}
public void creatClient() throws UnknownHostException, IOException {
// TODO Auto-generated method stub
//客户端创建一个socket连接服务器
InetAddress addr = InetAddress.getLocalHost();
socket = new Socket(addr,9000);
jt.append("连接...!\n");
input = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取输入流
output= new PrintStream(socket.getOutputStream()); //获取输出流
String s_code = input.readLine();
String text = "验证码为:"+ s_code +"\n";
jt.append(text);
verify = new File("src\\client\\output.txt");
if(!verify.exists()) {
verify.createNewFile();
}
BufferedWriter fileout = new BufferedWriter(new FileWriter(verify));
fileout.write(s_code);//将s_code存入文件
fileout.close();
}
//
// public void returncode() throws IOException {
// output= new PrintStream(socket.getOutputStream()); //获取输出流
// output.println(code);
// output.close();
// }
@SuppressWarnings("resource")
public void getflag() throws IOException {
// input = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取输入流
code = JOptionPane.showInputDialog("请输入你的验证码:");
jt.append("您输入的验证码为:"+code+"\n");
InputStreamReader reader = new InputStreamReader(new FileInputStream(verify)); // 建立一个输入流对象reader
BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
s_code = br.readLine(); //读取验证码
// System.out.println(code);
// System.out.println(s_code);
if(code.equals(s_code)) {
jt.append("验证成功!");
}
else {
jt.append("验证失败!");
}
output.close();
}
}
/*服务器*/
import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
import javax.swing.JTextArea;
public class server {
PrintStream output;
BufferedReader input;
ServerSocket server;
Socket socket;
String code ="";
String c_code;
JTextArea jt;
int flag;
public server() {
// TODO Auto-generated constructor stub
/*文本区域,显示信息*/
jt = new JTextArea();
jt.setBounds(100,50,250,200);
jt.setBackground(Color.lightGray);
jt.setEditable(false);
jt.setText("欢迎!\n");
}
/*建立一个服务器*/
public void setUpServer(int port) throws IOException {
jt.append("服务器建立中...\n");
server = new ServerSocket(port);//将端口设为服务器
socket = server.accept();//定义一个中介接收对象socket
jt.append("客户机已连接\n");
run();
}
public void run() throws IOException {
output= new PrintStream(socket.getOutputStream()); //获取输出流
/*生成验证码*/
String all="0123456789";
int codeLength = 6;
Random random = new Random();
for(int i=0;i<codeLength;i++) { //随机生成一段验证码
int num = random.nextInt(all.length());
code = code + all.substring(num,num+1);
}
output.println(code);
jt.append("验证码已发送!");
}
}
接下来只需要分别调用creatClient()和setUpServer()方法就OK了!
遇到的问题是服务器的JTextArea不会在调用append()方法后立即更新,而是会等到客户机连接成功后才会一次性更新出来,我认为这应该与java的线程和进程的机制有关。有待进一步的学习。