关于java实现群聊和同步画图小结。

论坛 期权论坛 脚本     
匿名网站用户   2020-12-20 17:48   46   0

这几天一直在做通信这方面的东西,刚开始的时候真的觉得不能很好的理解,但是同时也觉得

真的很神奇。现在就讲解一下我再这方面学到的东西,以及在学习的过程中所遇到的问题。
话不多说,先传上我的成果。



可能你刚开始的时候也会觉得这里有的东西是无法理解的。让我一步一步解释。
首先这是一个通信的问题,我记得有个人说过计算机因为有了通信而变得很不一样了,当时刚

听这句话是,没有明白到底是神马意思,学过通信过后才深刻的领悟了这句话。话不多说,开

启我们的通信之旅。

首先通信是有服务器和客户端构成的,也就是我们必须要通过服务器来实现链接,在java中有

这样的一个类 ServerSocket ;我们可以通过这个类创建一个服务器对象代码如下:

ServerSocket serverSocket = new ServerSocket(9090);

9090是我们创建的服务器的端口号,这个端口号是有1-60000多的数字,我们要竟可能挑选大

一点的数字,因为小的数字可能已经被系统占用,这样我们创建了一个服务器了,那么怎么与

客户端链接呢,看下面代码:

Socket socket = serverSocket.accept()

这句代码的意思是我们的服务器在等待客户端

来连接,如果没有链接那么整个程序就一直阻塞在这里,换句话说我们必须有客户端链接程序

才能继续运行,试想如果没有客户端链接,服务器还用运行吗,当我们获得socke对象后我们

就必须要获取服务器的输入输出流;看下面代码:

InputStream ins = socket.getInputStream();
OutputStream out = socket.getOutputStream();

那么我们为什么要获取输入流输出流呢?这是因为我们整个通信就是读写数据,我们要获取从

客户端输入的数据然后再进写给其他的客户端,同时我们客户端也要实现一些公告什么的功能

,我可以说整个服务器就是上面的四行代码。服务器就先到这了,我们接下来要说一下客户端

,同样客户端也是几行代码.首先我们要创建一个客户端,这个客户端要链接上服务器,看下

面的代码:

Socket socket = new Socket("localhost",9090);

这行代码是创建一个客户端,构造方法的第一个参数是服务器的ip地址,第二个参数是服务器

的端口号,这样就创建了一个客户端了 同样我们也要获取客户端的输入输出流;代码如下:

 InputStream ins = socket.getInputStream();
 OutputStream out = socket.getOutputStream();

这样我们应该大体上对客户端和服务器有了一定的了解了,让我举个形象化的列子吧。两桶水
在这两桶水中间有跟管道,当客户端与服务器连接上了,就打开管道阀门了,这时就可以传递

了,服务器那边写客户端就读,客户端写服务器就读。就此我也讲一下群聊的实现吧,就是我

客户端写给服务器读,当服务器读到了就发给每个链接上的客户端,这样就实现了群聊的功能

,你是不是也觉得挺简单的。
接下来我们通过一个群聊和同步画图实例来讲解。
先看上图:




接下来让我们来好好分析一下这个小项目,同时也将一下我在这个项目中遇到的问题。
首先看一下我们的项目的UML分析图:

先看我们的服务器的:



在看我们的客户端的:



现在我们再来说一下这个到底是怎么实现的,首先我们的服务器是创建成功了,但是我们在上面已经说过了

Socket socket = serverSocket.accept()

服务器是一直在等待客户端来连接,那么整个程序就不再向下运行了,这时候我们考虑到使用线程,这样我们就能很好的解决这个问题,因为线程是并发同时运行的。当我们解决好这个问题后,我们要考虑服务器的读取数据,在这个问题中跟客户端是一样的,因为我们客户端和服务器是一直在读取数据,那么也就是说

我们用一个死循环来调用读取的方法,代码如下:

 public void process(){
  
  try {
   ins = this.socket.getInputStream();
   out = this.socket.getOutputStream();
   dins =  new DataInputStream(ins);
   dout = new DataOutputStream(out);
   while (true) {
    byte b = dins.readByte();
    if(b==1){
     int x1 = dins.readInt();
     int y1 = dins.readInt();
     int x2= dins.readInt();
     int y2 = dins.readInt();
     transDate( b, x1, y1, x2, y2);
     g.drawLine(x1, y1, x2, y2);
    }else if(b==2){
     int x1 = dins.readInt();
     int y1 = dins.readInt();
     int x2= dins.readInt();
     int y2 = dins.readInt();
     transDate( b, x1, y1, x2, y2);
     g.drawOval(x1, y1, x2-x1, y2-y1);
    }else if(b==3){
     sendMsg();
    }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 //创建一个传输数据的方法
 public void transDate(byte b,int x1,int y1,int x2,int y2){
  
  int t = SeverThreadList.SeverList.size();
  for(int i=0;i<t;i++){
   try {
    SeverThreadList.SeverList.get(i).dout.writeByte(b);
    SeverThreadList.SeverList.get(i).dout.writeInt(x1);
    SeverThreadList.SeverList.get(i).dout.writeInt(y1);
    SeverThreadList.SeverList.get(i).dout.writeInt(x2);
    SeverThreadList.SeverList.get(i).dout.writeInt(y2);
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

上面我们用一个while的死循环,但是这时问题又来了,整个程序又卡在这里了,解决方法如上,也是放在一个线程里,这样就可以了;同样客户端也是这样处理的,就是我们将一个客户端的读取数据也放在线程里。

,接下来我们来说一下群聊的实现:

Socket socket = serverSocket.accept()

这是我们获取的socket,我要解释一下,这可socket是不一样的,也就是处理每个客户端的socket是不一样的,那么我们可以将它放入链表中,这样当服务器接受到客户端发来的信息,我们在遍历这个链表将信息发出去,这样我们就实现了群聊了,看下面代码:

public void createServer(){
  try {
   ServerSocket serverSocket = new ServerSocket(9090);
   System.out.println("服务器创建成功");
   while (true) {
    Socket socket = serverSocket.accept();
    System.out.println("有客户端连接了");
    IoThread ioThread = new IoThread(socket,this.g,area);
    SeverThreadList.SeverList.add(ioThread);
    ioThread.start();
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

//创建一个传输数据的方法
 public void transDate(byte b,int x1,int y1,int x2,int y2){
  
  int t = SeverThreadList.SeverList.size();
  for(int i=0;i<t;i++){
   try {
    SeverThreadList.SeverList.get(i).dout.writeByte(b);
    SeverThreadList.SeverList.get(i).dout.writeInt(x1);
    SeverThreadList.SeverList.get(i).dout.writeInt(y1);
    SeverThreadList.SeverList.get(i).dout.writeInt(x2);
    SeverThreadList.SeverList.get(i).dout.writeInt(y2);
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

这样我们就实现了群聊的功能了,接下来我再说一下我在写通信是所遇到的问题,有的注意点已经在上面讲过了,就不再赘述了。在实现通信时,要先注意你的通信协议,这个是通信的灵魂,比如我上面的项目就是我换线的时候我先写一个byte为1然后在写数据,我花圆的时候先写一个byte为2然后在写数据,这样当我接收到数据时就先读取这个byte数据,如果为1那么我就读取画线的数据,如果为2那么我就读取画圆的数据,

第2 要注意读取数据的细节之处,看下面的代码:

                                     c = (char)dins.read();
   while(c!='#'){
    message +=c;
    c = (char)dins.read();
   }
   message = new String(message.getBytes("ISO-8859-1"),"GB2312");

我们必须有一个读取结束的标志,在标志前的数据我们要保存。

这样我们就对通信有了一定的了解,后面就得靠自己来实际动手来做,我报上面的项目的代码放在附件中,如有问题,请给我留言。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP