java socket实现聊天室 java实现多人聊天功能

时间:2022-03-01 23:33:27

用java socket做一个聊天室,实现多人聊天的功能。看了极客学院的视频后跟着敲的。(1day)

服务端:

1. 先写服务端的类myserversocket,里面放一个监听线程,一启动就好
2. 实现服务端监听类serverlistener.java,用accept来监听,一旦有客户端连上,生成新的socket,就新建个线程实例chatsocket。启动线程后就把线程交给chatmanager管理
3. 在chatsocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端
4. chatmanager里面用vector来管理socket线程实例chatsocket,并实现发送信息给其他的客户端

客户端:

1. 新建一个继承jframe的mainwindow.java类,主要实现聊天窗口的ui,以及事件响应。
2. 新建startclient.java类,把mainwindow中生成mainwindow主方法部分代码拷贝过来,这样就能在主程序中把窗体执行出来了。
3. 新建chatmanager(需要单例化的类)管理socket,实现聊天的输入输出功能。最后记得在1中新建窗口后,传一份frame的引用到chatmanager中,才能实现chatmanager对界面的显示。

工程结构如图

java socket实现聊天室 java实现多人聊天功能

以下为代码

服务端:

1. 先写服务端的类myserversocket,里面放一个监听线程,一启动就好

?
1
2
3
4
5
6
7
8
package com.starnet.testserversocket.main;
 
 
public class myserversocket {
  public static void main(string[] args) {
    new serverlistener().start();
  }
}

2.实现服务端监听类serverlistener.java,用accept来监听,一旦有客户端连上,生成新的socket,就新建个线程实例chatsocket。启动线程后就把线程交给chatmanager管理

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.starnet.testserversocket.main;
 
import java.io.ioexception;
import java.net.serversocket;
import java.net.socket;
 
import javax.swing.joptionpane;
 
public class serverlistener extends thread {
  public void run() {
    try {
      serversocket serversocket = new serversocket(23456);
      while (true) {
        // block
        socket socket = serversocket.accept();
        // 建立链接
        joptionpane.showmessagedialog(null, "有客户端连到本机23456端口");
        //将socket传递给新的线程
        chatsocket cs= new chatsocket(socket);
        cs.start();
        chatmanager.getchatmanager().add(cs);
      }
    } catch (ioexception e) {
      e.printstacktrace();
    }
  }
}

3.在chatsocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.starnet.testserversocket.main;
 
import java.io.bufferedreader;
import java.io.ioexception;
import java.io.inputstreamreader;
import java.io.unsupportedencodingexception;
import java.net.socket;
/*每一个连上的客户端,服务器都有一个线程为之服务*/
public class chatsocket extends thread {
  socket socket;
 
  public chatsocket(socket s) {
    this.socket = s;
  }
 
  //发送数据
  public void out(string out) {
    try {
      socket.getoutputstream().write(out.getbytes("utf-8"));
    } catch (unsupportedencodingexception e) {
      // todo auto-generated catch block
      e.printstacktrace();
    } catch (ioexception e) {
      // todo auto-generated catch block
      e.printstacktrace();
    }
  }
 
  //服务器会不断地从客户端读取内容,把读取到的内容发给集合内所有的客户端。
  public void run() {
    try {
      //接收数据
      bufferedreader br = new bufferedreader(
          new inputstreamreader(
              socket.getinputstream(), "utf-8"));
      string line=null;
      //发送读到的内容
      while ((line = br.readline())!=null) {
        system.out.println(line);
        chatmanager.getchatmanager().publish(this, line);
      }
      br.close();
    } catch (ioexception e) {
      // todo auto-generated catch block
      e.printstacktrace();
    }
  }
}

4.chatmanager里面用vector来管理socket线程实例chatsocket,并实现发送信息给其他的客户端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.starnet.testserversocket.main;
 
import java.util.vector;
//一个聊天服务器只能有一个manager,要单例化处理
public class chatmanager {
  private chatmanager(){}
  private static final chatmanager cm=new chatmanager();
  public static chatmanager getchatmanager(){
    return cm;
  }
 
  vector<chatsocket> vector = new vector<chatsocket>();
  /*增加chatsocket 实例到vector中*/
  public void add(chatsocket cs){
    vector.add(cs);
  }
 
  /*发布消息给其他客户端
   *chatsocket cs: 调用publish的线程
   *msg:要发送的信息 */
  public void publish(chatsocket cs, string msg){
    for (int i = 0; i < vector.size(); i++) {
      chatsocket cstemp = vector.get(i);
      if (!cs.equals(cstemp)) {
        cstemp.out(msg+"\n");//不用发送给自己。
      }
    }
  }
 
}

客户端:

1. 新建一个继承jframe的mainwindow.java类,主要实现聊天窗口的ui,以及事件响应。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package com.starnet.javaclient.view;
 
import java.awt.borderlayout;
import java.awt.eventqueue;
 
import javax.swing.jframe;
import javax.swing.jpanel;
import javax.swing.border.emptyborder;
import javax.swing.jtextarea;
import javax.swing.grouplayout;
import javax.swing.grouplayout.alignment;
import javax.swing.jtextfield;
import javax.swing.jbutton;
import javax.swing.layoutstyle.componentplacement;
 
import com.starnet.javaclient.main.chatmanager;
import com.sun.xml.internal.ws.client.senderexception;
 
import java.awt.event.mouseadapter;
import java.awt.event.mouseevent;
 
public class mainwindow extends jframe {
 
  /**
   *
   */
  private static final long serialversionuid = 1l;
  private jpanel contentpane;
  private jtextarea txt;
  private jtextfield txtip;
  private jtextfield txtsend;
 
  /**
   * create the frame.
   */
  public mainwindow() {
    setalwaysontop(true);
    setdefaultcloseoperation(jframe.exit_on_close);
    setbounds(100, 100, 450, 300);
    contentpane = new jpanel();
    contentpane.setborder(new emptyborder(5, 5, 5, 5));
    setcontentpane(contentpane);
 
    txt = new jtextarea();
    txt.settext("ready...");
 
    txtip = new jtextfield();
    txtip.settext("127.0.0.1");
    txtip.setcolumns(10);
 
    jbutton btnconnect = new jbutton("connect");
    btnconnect.addmouselistener(new mouseadapter() {
      @override
      public void mouseclicked(mouseevent e) {
        chatmanager.getchatmanager().connect(txtip.gettext());
      }
    });
 
    txtsend = new jtextfield();
    txtsend.settext("hello");
    txtsend.setcolumns(10);
 
    jbutton btnsend = new jbutton("send");
    btnsend.addmouselistener(new mouseadapter() {
      @override
      public void mouseclicked(mouseevent e) {
        chatmanager.getchatmanager().send(txtsend.gettext());
        appendtext("我说: "+txtsend.gettext());
        txtsend.settext("");
      }
    });
    grouplayout gl_contentpane = new grouplayout(contentpane);
    gl_contentpane.sethorizontalgroup(
      gl_contentpane.createparallelgroup(alignment.leading)
        .addgroup(alignment.trailing, gl_contentpane.createsequentialgroup()
          .addgroup(gl_contentpane.createparallelgroup(alignment.trailing)
            .addgroup(gl_contentpane.createsequentialgroup()
              .addcomponent(txtsend, grouplayout.default_size, 325, short.max_value)
              .addpreferredgap(componentplacement.related)
              .addcomponent(btnsend, grouplayout.preferred_size, 109, grouplayout.preferred_size))
            .addgroup(alignment.leading, gl_contentpane.createsequentialgroup()
              .addcomponent(txtip, grouplayout.preferred_size, 294, grouplayout.preferred_size)
              .addpreferredgap(componentplacement.related)
              .addcomponent(btnconnect, grouplayout.default_size, 140, short.max_value))
            .addcomponent(txt, grouplayout.default_size, 434, short.max_value))
          .addcontainergap())
    );
    gl_contentpane.setverticalgroup(
      gl_contentpane.createparallelgroup(alignment.leading)
        .addgroup(gl_contentpane.createsequentialgroup()
          .addgroup(gl_contentpane.createparallelgroup(alignment.baseline)
            .addcomponent(txtip, grouplayout.preferred_size, grouplayout.default_size, grouplayout.preferred_size)
            .addcomponent(btnconnect))
          .addpreferredgap(componentplacement.related)
          .addcomponent(txt, grouplayout.default_size, 198, short.max_value)
          .addpreferredgap(componentplacement.related)
          .addgroup(gl_contentpane.createparallelgroup(alignment.trailing)
            .addcomponent(btnsend)
            .addcomponent(txtsend, grouplayout.preferred_size, grouplayout.default_size, grouplayout.preferred_size)))
    );
    contentpane.setlayout(gl_contentpane);
  }
  /*客户端发送的内容添加到中间的txt控件中*/
  public void appendtext(string in) {
    txt.append("\n" + in);
  }
}

2.新建startclient.java类,把mainwindow中生成mainwindow主方法部分代码拷贝过来,这样就能在主程序中把窗体执行出来了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.starnet.javaclient.main;
 
import java.awt.eventqueue;
 
import com.starnet.javaclient.view.mainwindow;
 
public class startclient {
  public static void main(string[] args) {
    /*先新建一个jframe,然后把自动生成的代码贴过来*/
    eventqueue.invokelater(new runnable() {
      public void run() {
        try {
          mainwindow frame = new mainwindow();
          frame.setvisible(true);
          //创建完这个frame以后,传一份window的引用到chatmanager去
          chatmanager.getchatmanager().setwindow(frame);
        } catch (exception e) {
          e.printstacktrace();
        }
      }
    });
  }
}

3.新建chatmanager(需要单例化的类)管理socket,实现聊天的输入输出功能。最后记得在1中新建窗口后,传一份frame的引用到chatmanager中,才能实现chatmanager对界面的显示。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.starnet.javaclient.main;
 
import java.io.bufferedreader;
import java.io.ioexception;
import java.io.inputstreamreader;
import java.io.outputstreamwriter;
import java.io.printwriter;
import java.net.socket;
import java.net.unknownhostexception;
 
import com.starnet.javaclient.view.mainwindow;
 
public class chatmanager {
  private chatmanager(){}
  private static final chatmanager instance=new chatmanager();
  public static chatmanager getchatmanager(){
    return instance;
  }
  mainwindow window;//为了能在界面上显示服务器发来的信息,就需要传一个mainwindow的引用进来
  socket socket;
  private string ip;
  bufferedreader breader;
  printwriter pwriter;
  public void setwindow(mainwindow window) {
    this.window = window;
    window.appendtext("文本框已经和chatmanager绑定了");
  }
  public void connect(string ip) {
    this.ip = ip;
    new thread(){
 
      @override
      public void run() {
        //实现网络方法
        try {
          socket = new socket(ip, 23456);
          //输出流
          pwriter = new printwriter(
              new outputstreamwriter(
                  socket.getoutputstream()));
          //输入流
          breader = new bufferedreader(
              new inputstreamreader(
                  socket.getinputstream()));
 
          string line = null;
          //如果读取数据为空
          while ((line = breader.readline())!=null) {
            window.appendtext("收到: "+line);
          }
          //读完数据之后要关闭
          pwriter.close();
          breader.close();
          pwriter = null;
          breader = null;
 
        } catch (unknownhostexception e) {
          e.printstacktrace();
        } catch (ioexception e) {
          e.printstacktrace();
        }
      }
    }.start();
  }
 
  public void send(string sendmsg){
    if (pwriter!=null) {
      pwriter.write(sendmsg+"\n");
      pwriter.flush();
    } else {
      window.appendtext("当前链接已经中断...");
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/u013427822/article/details/54947649