基于java的Socket简单知识做的多人聊天室

这是本人近期学期的一个总结,有什么讲的不妥之处请各位指出,感谢。

关于聊天室的代码网上也是一抓一大把,但是真正的能讲清楚初学者的想掌握的要点的文章还是有点少,在做之前也查了很多资料。首先,要做这个聊天室,你需要掌握的知识点有集合,泛型,服务器套接字,io,线程,swing以及异常捕获。聊天室的构成一般会有三部分组成,一般就是界面(Frame),聊天服务器(ChatServer)和聊天客户端(ChatClient)组成。在等会的代码中,我分为服务器和客户端两个方面,如果想做的好点就做三个class文件。服务器方面,我先用了用了一个Arraylist来存储客户端这个对象,

这边有个知识点就是为什么集合要用LIst呢,首先list主要的功能是用于储存,但Map主要用于建立对象的关联,Set的每种对象类型只能持有一个,So。然后就是用到了父类声明创建子类对象。接下来就是给给服务器指定本地端口,一共有65536个。然后让服务器死循环,用于不停的监听外面的客户端接入请求。每当接受客户端请求后就把它加入到当前的集合中,其实集合也就是个容器。接下来有客户端连入后,我们势必要做一个线程让服务器能够接受客户端发出的消息,然后把接收的消息发给其他的客户端中。其中这边的知识点就是当有多个客户端连入时,但谁在发出消息的那个时候线程应处于阻塞状态,防止两个客户端的消息被一起接收,然后出现异常,就像两个电脑要打印文件,不可能在一个打印机上同时打印。对于输入流输出流,就是服务器要不停的准备接受消息,如果没有死循环,消息就是每个客户端发一次就不能发了。然后输出流方面就是不要忘记刷新,不然消息也是会发不出的,对于这个我当时烦了一天,因为知识点没掌握,发现其他的io可以,就是bufferreader和printwriter不可以,就是没刷新,导致数据写入了缓冲区中,却没刷新发出去。至于客户端方面,基本没什么大的问题了,连入本地服务器端口,然后输出流放在发送的按钮中。记得流要关闭,先开后关。至于swing方面,我了解的不多,但是好像现在不怎么用了,所以没什么要讲的啦。上代码

public class ChatServer {
List<ClientThread> clients = new ArrayList<ClientThread>();
public static void main(String[] args) {
new ChatServer().go();
}
public  void go(){
try {
ServerSocket serversocket = new ServerSocket(12345);
while(true){
System.out.println("端口绑定");
Socket socket = serversocket.accept();
System.out.println("有外部客户端接入");
ClientThread currentClient = new ClientThread(socket);
clients.add(currentClient);
currentClient.start();
System.out.println("客户端线程开始");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class ClientThread extends Thread{
private Socket socket;
private BufferedReader bis;
private PrintWriter bos;
private String line;


public ClientThread(Socket socket){
this.socket = socket;
}


@Override
public void run() {
System.out.println("run方法启动了!");
try {
while(true){
bis = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
line = bis.readLine();
System.out.println("接收到消息");
for(int i=0; i<clients.size(); i++){

ClientThread c = clients.get(i);
c.send(line);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
public void send(String line){
try {
bos = new PrintWriter(
new OutputStreamWriter(
socket.getOutputStream()));
bos.println(line);
bos.flush();
System.out.println("正在向客户端写消息成功!");


} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
}


}


public class ChatClient {
private JTextArea ta;
private JTextField tf;
private JButton b;
private BufferedReader bis;
private PrintWriter bos;
private Socket socket;
public static void main(String[] args) {
new ChatClient().frame();
}
public void frame(){
JFrame f = new JFrame("BB");
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
ta = new JTextArea(12, 30); // 文本域,第一个参数为行数,第二个参数为列数
ta.setEditable(false); // 文本域只读
JScrollPane sp = new JScrollPane(ta); // 滚动窗格
tf = new JTextField(20);
b = new JButton("发送");
p1.add(sp);
p2.add(tf);
p2.add(b);
f.add(p1, "Center");
f.add(p2, "South");
f.setBounds(300, 300, 360, 300);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.b.addActionListener(new TFListener());
this.connect();


}
public void connect(){
try {
socket = new Socket("127.0.0.1", 12345);
bos = new PrintWriter(
(socket.getOutputStream()));
bis = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
new sendThread().start();

} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
class TFListener implements ActionListener{
        private String str;
        @Override
        public void actionPerformed(ActionEvent e) {
            str = tf.getText()+"\n";
            tf.setText("");
//            ta.append(str);
            bos.println(str);
            bos.flush();
            
        }
        
    }
class sendThread extends Thread{
private String str;
@Override
public void run() {
recMsg();
}
public void recMsg(){
try {
while(true){
str = bis.readLine()+"\n";
ta.append(str);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 
 
}
}
}

部分代码如下:client: /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package client; /** * * @author Administrator */ import java.awt.*; import java.io.*; import java.net.*; import java.applet.*; import java.util.Hashtable; public class ClientChat extends Applet implements Runnable { Socket socket=null; DataInputStream in=null; DataOutputStream out=null; InputNameTextField 用户提交昵称界面=null; ChatArea 用户聊天界面=null; Hashtable listTable; Label 提示条; Panel north, center; Thread thread; public void init() { int width=getSize().width; int height=getSize().height; listTable=new Hashtable(); setLayout(new BorderLayout()); 用户提交昵称界面=new InputNameTextField(listTable); int h=用户提交昵称界面.getSize().height; 用户聊天界面=new ChatArea("",listTable,width,height-(h+5)); 用户聊天界面.setVisible(false); 提示条=new Label("正在连接到服务器,请稍等...",Label.CENTER); 提示条.setForeground(Color.red); north=new Panel(new FlowLayout(FlowLayout.LEFT)); center=new Panel(); north.add(用户提交昵称界面); north.add(提示条); center.add(用户聊天界面); add(north,BorderLayout.NORTH); add(center,BorderLayout.CENTER); validate(); } public void start() { if(socket!=null&&in!=null&&out!=null) { try { socket.close(); in.close(); out.close(); 用户聊天界面.setVisible(false); } catch(Exception ee) { } } try { socket = new Socket(this.getCodeBase().getHost(), 6666); in=new DataInputStream(socket.getInputStream()); out=new DataOutputStream(socket.getOutputStream()); } catch (IOException ee) { 提示条.setText("连接失败"); } if(socket!=null) { InetAddress address=socket.getInetAddress(); 提示条.setText("连接:"+address+"成功"); 用户提交昵称界面.setSocketConnection(socket,in,out); north.validate(); } if(thread==null) { thread=new Thread(this); thread.start(); } } public void stop() { try { socket.close(); thread=null; } catch(IOException e) { this.showStatus(e.toString()); } } public void run() { while(thread!=null) { if(用户提交昵称界面.get能否聊天()==true) { 用户聊天界面.setVisible(true); 用户聊天界面.setName(用户提交昵称界面.getName()); 用户聊天界面.setSocketConnection(socket,in,out); 提示条.setText("祝聊天愉快!"); center.validate(); break; } try { Thread.sleep(100); } catch(Exception e) { } } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值