团队冲刺DAY7
今天是2019.6.2,交项目的最后一天。
今天的任务是将之前写好的服务器和加解密算法以及图形界面有机结合在一起。
早上8:00,坐在电脑前,一脸懵,因为图形界面不是很懂,所以不知道应该怎么做。
所以在网上找了相关的代码,看了一上午,下午发现一点相同点,就是将客户端和服务器的接收和发送写成两个线程,并将组件的操作替换成输出和输入。
虽然我们的服务器和客户端就是按照这样的思路写出来的,但是上午的时候,走偏了,将接收和发送两个操作都写在监听事件中了,这就造成,只有当客户端和服务器都点击输入键之后,才会出现三次握手。
下面是客户端聊天过程用于发送信息的线程
class Receive extends Thread {
Socket socket;
public Receive(Socket sock) {
this.socket = sock;
}
@Override
public void run() {
// 专门用于接收消息
DataInputStream in;
while (true) {
try {
in = new DataInputStream(socket.getInputStream());
String str = in.readUTF();
client.PoliceListen.stringPrint(str);
} catch (Exception e) {
}
}
}
}
这其中的组件操作就是:
client.PoliceListen.stringPrint(str);
通过将监听类中设置方法,并将这些类都放在一个package中的方法来调用其他类的方法。
当然这不是最终的代码,因为按照要求,在通讯的过程中还要进行加密和解密。
在这个阶段,我还遇到一个问题。
class Send extends Thread {
Socket socket;
public Send(Socket sock) {
this.socket = sock;
}
// 专门用于发送信息
@Override
public void run() {
DataOutputStream out;
String str="";
while (true) {
str = client.PoliceListen.pass();
try {
out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
问题就是在这前PoliceListen类中定义了public static类型的变量 String pa(pa变量是用来监听图形界面输入的字符串),并将增加了返回这个字符串的方法pass,但是在输出环节的 Send类中,因为是通过循环来输出图形界面的输入,所以如果不加以控制的话,会一直输出pa,直到图形界面输入了其他的pa值,并继续一直输出下一个pa值。
解决方法:
class Send extends Thread {
Socket socket;
public Send(Socket sock) {
this.socket = sock;
}
// 专门用于发送信息
@Override
public void run() {
DataOutputStream out;
String str="";
while (true) {
str = client.PoliceListen.pass();
if(!temp.equals(str)){
temp = str;
try {
out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
通过比较临时变量temp和public static 类型的pa变量的方法来确定是否图形界面是否有新的输入值。
从而比较好的解决了一直无脑输出的情况。
(目前没想到特别好的方法)
大结局
在客户端和服务器加入加密和解密的环节。
这个环节在之前没有图形界面的时候,就已经熟练掌握了,只需要写好加密和解密的接口,如何直接用就可以了。我们之前选定的是DES,因为那个时候刚好密码学讲到DES(没选AES是因为定加密算法的时候,还没学)。
我们除了在网上找了相关的代码,并通过我们的验证和修改,以及编写DESUtil接口,完成了这部分的内容。
加密和解密的部分是通过最简单的内置密钥的方式,还可以换成实验五的DH交换密钥等其他算法。
package client;
import java.net.*;
import java.io.*;
import java.nio.charset.Charset;
//聊天过程用于发送信息的线程
class Send extends Thread {
Socket socket;
private static final String SKEY = "abcdefgh";
private static final Charset CHARSET = Charset.forName("gb2312");
public Send(Socket sock) {
this.socket = sock;
}
// 专门用于发送信息
@Override
public void run() {
DataOutputStream out;
String str="";
String temp="3C5CA5E51F7D0F8A";
while (true) {
str = client.PoliceListen.pass();
str = client.DesUtil.encrypt(str, CHARSET, SKEY);
if(!temp.equals(str)){
temp = str;
try {
out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
// 创建一个专门用于接收消息的线程
class Receive extends Thread {
Socket socket;
private static final String SKEY = "abcdefgh";
private static final Charset CHARSET = Charset.forName("gb2312");
public Receive(Socket sock) {
this.socket = sock;
}
@Override
public void run() {
// 专门用于接收消息
DataInputStream in;
while (true) {
try {
in = new DataInputStream(socket.getInputStream());
String str = in.readUTF();
client.PoliceListen.stringPrint("服务器发来:"+str);
str = client.DesUtil.decrypt(str, CHARSET, SKEY);
client.PoliceListen.stringPrint("解密为"+str);
} catch (Exception e) {
}
}
}
}
public class Client {
static Socket socket;
public static void main(String[] args) throws Exception {
socket = new Socket("127.0.0.1", 5678);
System.out.println("客户端.....");
try {
Send send = new Send(socket);
Receive receive = new Receive(socket);
WindowActionEvent win=new WindowActionEvent();
PoliceListen police = new PoliceListen();
//创建监视器
win.setMyCommandListener(police);
//窗口组合监视器
win.setBounds(100,100,460,360);
win.setTitle("信息系统——客户端");
// 打开线程
send.start();
receive.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
废话不多说,看图!