上一篇仿照大佬的写了一个简单的向客户机写循环变量,经过一天的探索双方终于可以进行交互了。下面进行分享。下面是最终的执行效果,上面两个调试控件碍眼请忽略
下面是程序截图
我一点点解释它。
这个位置相当于Java为ServerSocket创建了构造函数的参数,注意是参数,并没有创建ServerSocket ,意思是这个ServerSocket监听的是哪个端口。就是一些初始化ServerSocket的参数,25000为监听端口,-1表示如果没有连接,则无限等待不超时。
这里才是创建ServerSocket,根据之前给的初始化参数。可以看到我们用一个while套着它,意思是可以监听到不同的socket连接,即可以有多个客户端连接(但是本示例没有考虑这种情况,如果有多个连接,消息会显示在一个控件中,高级语言的面向对象可以很好的解决这个问题,这里就不纠结这个了,我们只有一个Java客户端)。从 上面的那个控件UI上面有个小的W旁边的那根线就是Java中对应的Socket类对象实例,可以看到我们连接了里层的两个while循环,并通过移位寄存器反复赋值,意思就是不要销毁这个socket对象(连接)。
在这里用了事件结构,发送按钮被按下就会跳到真里面,读取标签为‘你要发送什么’的这个控件里面的内容,通过添加开始标志‘start||’,以及结束标志‘end||’,包装后,将流推送到网络上,为什么要这么设计呢,其实一开始我也不是这么设计的,但是经过我的反复实验,只有这样,在Java端想要拿到有效数据才比较容易。在Java端建立一个1000Byte大小的数组,将来自服务器的数据全部转为字符串,用IndexOf函数得到开始标志,结束标志的位置,就可以通过String.subString()函数,传入‘start||’.length+开始标志位置,以及结束标志位置,就可以得到有效数据,即服务器发过来的数据。
此外可以看到上图还连接了一个分支,是用来在服务器端显示自己说了什么的,既然是聊天得人性化一点,将收到的和自己说的放到一个显示框,方便阅读。我们先读取原聊天控件里面的内容,加上‘服务器说:’这个标签,加上自己刚才要发的内容,加上换行符,写入显示控件中。这样控件就能正确显示自己说了什么了。
我们来看另一个分支,这个是读取客户端发过来消息的分支,首先说明,我在java端写的客户端消息统一以||**||**||结尾,这样的话更方便解析有效信息,因为目前接触到的读取函数是要指定读取多少的,我们指定为1000,和Java端保持一致,Java端如果消息长度不足1000,则将有效消息,加上结尾符号,再加一些无关紧要的东西填充至1000Byte。如果第一次消息来了,我们首先搜寻结尾符在消息中的位置,得到位置后截取字符串,然后组合字符串,组合字符串的格式为以前的消息+客户端说:+本次的消息+换行。之后写入聊天记录这个控件中,之后再把socket句柄和旧的聊天记录传给下一次循环。这样新的消息来,就能在原有消息上增加。至此程序分析完毕。
这次的尝试主要是知道了移位寄存器配合while使用可以类似于达到局部变量保持的效果,可以对于复杂的数据结构还没掌握,不然可以将socket句柄和每一个对话框这些每一个客户端,服务器的必要元素封装成一个类,这样就可以多用户和服务器聊天了。
说到这里,我发现有好多好多学习的人不明白局域网这个概念,至少大学阶段学习完计算机网络,百分之七八十不知道云服务器干什么用的,不知道公网IP的作用。这里也多啰嗦几句,我们可以使用cmd打开命令行窗口通过ipconfig-all命令看到自己的ip地址都是192.168.***.***,其实这只是个私网ip地址,设想如果你自己的ip是192.168.31.10,别人的也是,那么ip还怎么唯一索引到一台计算机呢。或许有人会问,你怎么知道我的私网地址和别人重复了,那么我想问一个问题,难道大家不好奇某品牌的新路由器(其实一定程度上只是个局域网交换机)配置地址都是192.168.31.1,为什么配置的时候不会进入别人的路由器呢。所以你那只是个私网,那公网的特征是什么呢,这个是范围的,比如我一个云服务器的例子为8.141.93.19(这里只是举个例子,这是个公网ip地址),回到这个Labview的例子,如果这个程序在这台公网上执行,那么就算服务器在(即LabView)在北京运行,你Java程序客户端在长沙,也是可以互相通信的(前提是你在我Java代码中把服务器的IP地址改为以上公网ip地址)。下面分享Java端代码。这是Main.java
import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Main { public static void main(String[] args) throws Exception{ Socket socket = new Socket("127.0.0.1", 25000); Scanner sin=new Scanner(System.in); new Thread(new Reader(socket)).start(); while(true){ String message=sin.nextLine(); System.out.println("客户端说:"+message); message+="||**||**||"; OutputStream os=socket.getOutputStream(); byte[] buffer_mess=message.getBytes(); byte[] fill_byte=new byte[1000]; System.arraycopy(buffer_mess, 0, fill_byte, 0, Math.min(buffer_mess.length, fill_byte.length)); os.write(fill_byte); os.flush(); } } }
这是Reader.java
import java.io.InputStream; import java.net.Socket; public class Reader extends Thread{ Socket socket; public Reader(Socket socket){ this.socket=socket; } public void run(){ String startFlag="start||"; String endFlag="end||"; while(true){ try { InputStream ins=socket.getInputStream(); int len=0; byte[] arr=new byte[1024]; ins.read(arr); String mess=new String(arr,0,arr.length); int start=mess.indexOf(startFlag); int end=mess.indexOf(endFlag); start+=startFlag.length(); mess=mess.substring(start,end); System.out.println("服务器说:"+mess); } catch (Exception e) { throw new RuntimeException(e); } } } }
如需要vi代码的请留言