用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对界面的显示。
工程结构如图
以下为代码
服务端:
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
查看更多关于java socket实现聊天室 java实现多人聊天功能的详细内容...