实验任务六

编程实现一个简单的聊天程序-多线程编程实现

1、 系统设计要求

编程实现一个简单的聊天程序,实现两台计算机间的信息交互,使用多线程编程实现;可同时连接多个客户端,服务器收到客户端发送的消息后转发给所有连接到服务器的客户端。客户端可以随时随地的发送信息。

2、 设计思路与方案

1) 设计思路
① 客户端设计思路:

  1. 设计好客户端的界面,包括待发送的消息的文本框,以及可以点击发送的发送消息按钮,以及接收消息的文本区域。
  2. 创建Socket套接字,配置好地址与端口号,实例化向服务器写的字节流以及实例化向服务器的字节流。
  3. 创建线程:在线程中对服务器转发的字节流进行监听,每监测到一行数据便将这行数据显示到接收消息的文本区域。
  4. 每次点击发送按钮时,读取输入区的文字并将其发送至服务器,发送的数据格式为用户名+消息条数目+“:”+消息具体内容。
    ② 服务器设计思路:
  5. 因为每一个客户端实例都需要与服务器建立向服务器的写字节流,故每登录一个新的客户端时则都会建立起一个新的线程,用以建立向服务器的写字节流以及监听每一个客户端是否有消息发送。
  6. 采用方法是服务器端每接收到一个新的客户端链接请求时便创建一个新的客户端对象,在每一个客户端对象中都有一个线程用于建立向服务器的写字节流以及监听每一个客户端是否有消息发送。
  7. 一旦监听到其中一个或多个客户端发送消息时,服务器端读取到发送的内容并将其转发给所有的已连接上服务器的客户端。
  8. 因为需要转发给所有的客户端对象,故在创建新的客户端对象是,会将该新的客户端对象存储在一个ArrayList集合中,在读取到消息时,遍历该集合中的所有客户端然后分别向其发送收到的内容。
    2) 程序总体框图

    3) 程序算法模块
    ① 客户端:
    1.建立链接:
    public void startUp(String name){userName=name;try{Socket sock=new Socket("127.0.0.1",4242);out=new ObjectOutputStream(sock.getOutputStream());in =new ObjectInputStream(sock.getInputStream());Thread remote=new Thread(new RemoteReader());remote.start();}catch(Exception ex){System.out.println("couldn`t connect-you`ll have to play alone.");}setUpMidi();buildGUI();}

2.建立客户端界面:

    public void buildGUI(){theFrame=new JFrame("Cyber BeatBox");BorderLayout layout=new BorderLayout();theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);JPanel background=new JPanel(layout);background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));checkboxList=new ArrayList<JCheckBox>();Box buttonBox=new Box(BoxLayout.Y_AXIS);JButton start=new JButton("Start");start.addActionListener(new MyStarListener());buttonBox.add(start);JButton stop=new JButton("Stop");stop.addActionListener(new MyStopListener());buttonBox.add(stop);JButton upTempo=new JButton("Tempo Up");upTempo.addActionListener(new MyUpTempoListener());buttonBox.add(upTempo);JButton downTempo=new JButton("Tempo down");downTempo.addActionListener(new MyDownTempoListener());buttonBox.add(downTempo);JButton sendIt=new JButton("sendIt");sendIt.addActionListener(new MySendListener());buttonBox.add(sendIt);userMessage=new JTextField();buttonBox.add(userMessage);incomingList=new JList();incomingList.addListSelectionListener(new MyListSelectionListener());incomingList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);JScrollPane theList=new JScrollPane(incomingList);buttonBox.add(theList);incomingList.setListData(listVector);Box nameBox=new Box(BoxLayout.Y_AXIS);for(int i=0;i<16;i++){nameBox.add(new Label(instrumentNames[i]));}background.add(BorderLayout.EAST,buttonBox);background.add(BorderLayout.WEST,nameBox);theFrame.getContentPane().add(background);GridLayout grid=new GridLayout(16,16);grid.setVgap(1);grid.setHgap(2);mainPanel=new JPanel(grid);background.add(BorderLayout.CENTER,mainPanel);for(int i=0;i<256;i++){JCheckBox c=new JCheckBox();c.setSelected(false);checkboxList.add(c);mainPanel.add(c);}theFrame.setBounds(50,50,300,300);theFrame.pack();theFrame.setVisible(true);}

3.客户端线程:

    public class RemoteReader implements Runnable{boolean[] checkboxState=null;String nameToShow=null;Object obj=null;public void run(){try{while((obj=in.readObject())!=null){System.out.println("got an object from server");System.out.println(obj.getClass());String nameToShow=(String) obj;checkboxState=(boolean[]) in.readObject();otherSeqsMap.put(nameToShow,checkboxState);listVector.add(nameToShow);incomingList.setListData(listVector);}}catch(Exception ex){ex.printStackTrace();}}}

4.监听发送按钮:

    public class MySendListener implements ActionListener{public void actionPerformed(ActionEvent a){boolean[] checkboxState=new boolean[256];for(int i=0;i<256;i++){JCheckBox check=(JCheckBox) checkboxList.get(i);if(check.isSelected()){checkboxState[i]=true;}}String messageToSend=null;try{out.writeObject(userName+ nextNum++ +": " + userMessage.getText());out.writeObject(checkboxState);}catch(Exception ex){System.out.println("Sorry dude. Could not send it to the server.");}userMessage.setText("");}}

② 服务器:
1.建立某个客户端链接:

    public void go(){clientOutputStreams=new ArrayList<ObjectOutputStream>();try{ServerSocket serversock=new ServerSocket(4242);while(true){Socket clientSocket=serversock.accept();ObjectOutputStream out=new ObjectOutputStream(clientSocket.getOutputStream());clientOutputStreams.add(out);Thread t=new Thread(new ClientHandler(clientSocket));t.start();System.out.println("got a connection");}}catch(Exception ex){ex.printStackTrace();}}

2.客户端内部类(包含线程):

    public class ClientHandler implements Runnable{ObjectInputStream in;Socket clientSocket;public ClientHandler(Socket socket){try{clientSocket=socket;in= new ObjectInputStream(clientSocket.getInputStream());}catch(Exception ex){ex.printStackTrace();}}public void run(){Object o2=null;Object o1=null;try{while((o1=in.readObject())!=null){o2=in.readObject();System.out.println("read two objects");tellEveryone(o1,o2);}}catch(Exception ex){ex.printStackTrace();}}}

3.运行结果示例

聊天结果示例1:

聊天结果示例2:

服务器响应:

4.完整代码

客户端(客户端运行时需输入字符串参数,如:“xx同学”):

import java.awt.*;
import javax.swing.*;
import java.io.*;
import javax.sound.midi.*;
import java.util.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.event.*;
import javax.swing.Box;public class BeatBoxFinal{JFrame theFrame;JPanel mainPanel;JList incomingList;JTextField userMessage;ArrayList<JCheckBox> checkboxList;int nextNum;Vector<String> listVector=new Vector<String>();String userName;ObjectOutputStream out;ObjectInputStream in;HashMap<String,boolean[]> otherSeqsMap=new HashMap<String,boolean[]>();Sequencer sequencer;Sequence sequence;Sequence mySequence=null;Track track;String[] instrumentNames={"Bass Drum","Closed Hi-Hat","Open Hi-Hat","Acoustic Snare","Crash Cymbal","Hand Clap","High Tom","Hi Bongo","Maracas","Whistle","Low Conga","Cowbell","Vibraslap","Low-mid Tom","High Agogo","Open Hi Conga"};int[] instruments={35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63};public static void main(String[] args){new BeatBoxFinal().startUp(args[0]);}public void startUp(String name){userName=name;try{Socket sock=new Socket("127.0.0.1",4242);out=new ObjectOutputStream(sock.getOutputStream());in =new ObjectInputStream(sock.getInputStream());Thread remote=new Thread(new RemoteReader());remote.start();}catch(Exception ex){System.out.println("couldn`t connect-you`ll have to play alone.");}setUpMidi();buildGUI();}public void buildGUI(){theFrame=new JFrame("Cyber BeatBox");BorderLayout layout=new BorderLayout();theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);JPanel background=new JPanel(layout);background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));checkboxList=new ArrayList<JCheckBox>();Box buttonBox=new Box(BoxLayout.Y_AXIS);JButton start=new JButton("Start");start.addActionListener(new MyStarListener());buttonBox.add(start);JButton stop=new JButton("Stop");stop.addActionListener(new MyStopListener());buttonBox.add(stop);JButton upTempo=new JButton("Tempo Up");upTempo.addActionListener(new MyUpTempoListener());buttonBox.add(upTempo);JButton downTempo=new JButton("Tempo down");downTempo.addActionListener(new MyDownTempoListener());buttonBox.add(downTempo);JButton sendIt=new JButton("sendIt");sendIt.addActionListener(new MySendListener());buttonBox.add(sendIt);userMessage=new JTextField();buttonBox.add(userMessage);incomingList=new JList();incomingList.addListSelectionListener(new MyListSelectionListener());incomingList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);JScrollPane theList=new JScrollPane(incomingList);buttonBox.add(theList);incomingList.setListData(listVector);Box nameBox=new Box(BoxLayout.Y_AXIS);for(int i=0;i<16;i++){nameBox.add(new Label(instrumentNames[i]));}background.add(BorderLayout.EAST,buttonBox);background.add(BorderLayout.WEST,nameBox);theFrame.getContentPane().add(background);GridLayout grid=new GridLayout(16,16);grid.setVgap(1);grid.setHgap(2);mainPanel=new JPanel(grid);background.add(BorderLayout.CENTER,mainPanel);for(int i=0;i<256;i++){JCheckBox c=new JCheckBox();c.setSelected(false);checkboxList.add(c);mainPanel.add(c);}theFrame.setBounds(50,50,300,300);theFrame.pack();theFrame.setVisible(true);}public void setUpMidi(){try{sequencer=MidiSystem.getSequencer();sequencer.open();sequence=new Sequence(Sequence.PPQ,4);track=sequence.createTrack();sequencer.setTempoInBPM(120);}catch(Exception e){e.printStackTrace();}}public void buildTrackAndStart(){ArrayList<Integer> trackList=null;sequence.deleteTrack(track);track=sequence.createTrack();for(int i=0;i<16;i++){trackList=new ArrayList<Integer>();for(int j=0;j<16;j++){JCheckBox jc=(JCheckBox) checkboxList.get(j+(16*i));if(jc.isSelected()){int key=instruments[i];trackList.add(new Integer(key));}else{trackList.add(null);}}makeTracks(trackList);}track.add(makeEvent(192,9,1,0,15));try{sequencer.setSequence(sequence);sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);sequencer.start();sequencer.setTempoInBPM(120);}catch(Exception e){e.printStackTrace();}}public class MyStarListener implements ActionListener{public void actionPerformed(ActionEvent a){buildTrackAndStart();}}public class MyStopListener implements ActionListener{public void actionPerformed(ActionEvent a){sequencer.stop();}}public class MyUpTempoListener implements ActionListener{public void actionPerformed(ActionEvent a){float tempoFactor=sequencer.getTempoFactor();sequencer.setTempoFactor((float)(tempoFactor*1.03));}}public class MyDownTempoListener implements ActionListener{public void actionPerformed(ActionEvent a){float tempoFactor=sequencer.getTempoFactor();sequencer.setTempoFactor((float)(tempoFactor*0.97));}}public class MySendListener implements ActionListener{public void actionPerformed(ActionEvent a){boolean[] checkboxState=new boolean[256];for(int i=0;i<256;i++){JCheckBox check=(JCheckBox) checkboxList.get(i);if(check.isSelected()){checkboxState[i]=true;}}String messageToSend=null;try{out.writeObject(userName+ nextNum++ +": " + userMessage.getText());out.writeObject(checkboxState);}catch(Exception ex){System.out.println("Sorry dude. Could not send it to the server.");}userMessage.setText("");}}public class MyListSelectionListener implements ListSelectionListener{public void valueChanged(ListSelectionEvent le){if(le.getValueIsAdjusting()){String selected=(String) incomingList.getSelectedValue();if(selected!=null){boolean[] selectedState=(boolean[]) otherSeqsMap.get(selected);changeSequence(selectedState);sequencer.stop();buildTrackAndStart();}}}}public class RemoteReader implements Runnable{boolean[] checkboxState=null;String nameToShow=null;Object obj=null;public void run(){try{while((obj=in.readObject())!=null){System.out.println("got an object from server");System.out.println(obj.getClass());String nameToShow=(String) obj;checkboxState=(boolean[]) in.readObject();otherSeqsMap.put(nameToShow,checkboxState);listVector.add(nameToShow);incomingList.setListData(listVector);}}catch(Exception ex){ex.printStackTrace();}}}public class MyPlayMineListener implements ActionListener{public void actionPerformed(ActionEvent a){if(mySequence!=null){sequence=mySequence;}}}public void changeSequence(boolean[] checkboxState){for(int i=0;i<256;i++){JCheckBox check=(JCheckBox) checkboxList.get(i);if(checkboxState[i]){check.setSelected(true);}else{check.setSelected(false);}}}public void makeTracks(ArrayList list){Iterator it=list.iterator();for(int i=0;i<16;i++){Integer num=(Integer) it.next();if(num!=null){int numKey=num.intValue();track.add(makeEvent(144,9,numKey,100,i));track.add(makeEvent(128,9,numKey,100,i+1));}}}public MidiEvent makeEvent(int comd,int chan,int one,int two,int tick){MidiEvent event=null;try{ShortMessage a=new ShortMessage();a.setMessage(comd,chan,one,two);event=new MidiEvent(a,tick);}catch(Exception e){e.printStackTrace();}return event;}
}

服务端:

import java.io.*;
import java.net.*;
import java.util.*;class MusicServer{ArrayList<ObjectOutputStream> clientOutputStreams;public static void main(String[] args){new MusicServer().go();}public class ClientHandler implements Runnable{ObjectInputStream in;Socket clientSocket;public ClientHandler(Socket socket){try{clientSocket=socket;in= new ObjectInputStream(clientSocket.getInputStream());}catch(Exception ex){ex.printStackTrace();}}public void run(){Object o2=null;Object o1=null;try{while((o1=in.readObject())!=null){o2=in.readObject();System.out.println("read two objects");tellEveryone(o1,o2);}}catch(Exception ex){ex.printStackTrace();}}}public void go(){clientOutputStreams=new ArrayList<ObjectOutputStream>();try{ServerSocket serversock=new ServerSocket(4242);while(true){Socket clientSocket=serversock.accept();ObjectOutputStream out=new ObjectOutputStream(clientSocket.getOutputStream());clientOutputStreams.add(out);Thread t=new Thread(new ClientHandler(clientSocket));t.start();System.out.println("got a connection");}}catch(Exception ex){ex.printStackTrace();}}public void tellEveryone(Object one,Object two){Iterator it=clientOutputStreams.iterator();while(it.hasNext()){try{ObjectOutputStream out=(ObjectOutputStream) it.next();out.writeObject(one);out.writeObject(two);}catch(Exception ex){ex.printStackTrace();}}}}

通信软件基础B-重庆邮电大学-Java-编程实现一个简单的聊天程序-多线程编程实现相关推荐

  1. JAVA同时输入用户名和密码_用java模拟设计一个简单的“用户注册”程序。当用户输入用户名和密码时,单击“注...

    用java模拟设计一个简单的"用户注册"程序.当用户输入用户名和密码时,单击"注 2020 - 9 - 26 TAG : 所有功能均已实现,如有不满意的地方我再修改imp ...

  2. 用switch语句编程设计一个简单的计算器程序

    用switch语句编程设计一个简单的计算器程序. 要求根据用户从键盘输入的表达式(注意操作数与运算符之间没有空格): 操作数1 运算符op 操作数2 计算表达式的值,指定的算术运算符为加(+).减(- ...

  3. 编程设计一个简单的计算器程序,要求根据用户从键盘输入的表达式,操作数

    编程设计一个简单的计算器程序,要求根据用户从键盘输入的表达式,操作数 首先,先写出各类计算的函数,参数从主函数中提取,返回计算后所得的值 因计算器不只要求能计算加减乘除,所以所有函数类型都为doubl ...

  4. 编程设计一个简单的计算器程序

    要求 用switch语句编程设计一个简单的计算器程序.要求根据用户从键盘输入的表达式. 操作数1 运算符op 操作数2 计算表达式的值.指定的算术运算符为加(+).减(-).乘(*).除(/). 当除 ...

  5. 编写用switch语句编程设计一个简单的计算器程序

    编程要求 根据提示,在右侧编辑器补充代码.要求用switch语句编程设计一个简单的计算器程序.要求根据用户从键盘输入的表达式. 操作数1 运算符op 操作数2 计算表达式的值.指定的算术运算符为加(+ ...

  6. c语言12之编程设计一个简单的计算器程序,要求根据用户从键盘输入的表达式:操作数1 运算符op 操作数2 计算表达式的值,指定的运算符为加减乘除。

    题目: 设计一个简单的计算器程序,要求根据用户从键盘输入的表达式: 操作数1 运算符op 操作数2 计算表达式的值,指定的运算符为加减乘除. 源代码: #include<stdio.h> ...

  7. 简单网络聊天程序java_基于Java实现hello/hi简单网络聊天程序

    Socket简要阐述 Socket的概念 Socket的英文原义是"孔"或"插座". 在网络编程中,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连 ...

  8. JAVA——如何写一个简单的聊天框

    这是上学期JAVA选修课课下的一道简单的线上家庭作业题,题目描述如下: 总的来说就是要按照它的描述写一个聊天室界面.由于是选修课要求不高,老师只要求我们写出大致界面即可不用实现具体功能,不过闲来无事我 ...

  9. java 内部类_Java内部类总结有哪些 没有基础该怎么学Java?

    Java内部类总结有哪些?没有基础该怎么学Java?互联网时代,掌握一门潮流的编程语言就意味着高薪和广阔的就业前景,而Java是很多人的一致选择.Java仍然无人可比,在国内的软件开发企业中,Java ...

最新文章

  1. 重磅!2022QS世界大学排名公布!
  2. iOS 检查指定日期是否在当前日期之前
  3. python服务器qt客户端_python3+PyQt5 创建多线程网络应用-TCP客户端和TCP服务器实例...
  4. [html] iframe如何自动调整高度?
  5. [转] 为你的项目选择一个合适的开源协议
  6. jmeter抓取cnode网站token值
  7. axios 中文文档
  8. -未来世界的幸存者- 读后感(现实篇和职业篇)
  9. java识别手写文字_Java 实现OCR 识别图像文字(手写中文)----tess4j
  10. 数据结构c语言版李冬梅PDF,数据结构(C语言版) 习题答案 严蔚敏 李冬梅 吴伟民 23490数据结构习题答案.pdf...
  11. 紫罗兰永恒花园rust简谱_みちしるべ简谱-紫罗兰永恒花园ed
  12. 我的爬虫 之 爬今日头条街拍图片
  13. spring boot 整合 jpa
  14. STM32中的PWM的频率和占空比的设置
  15. 如何用微信编辑器排版出美观的图文消息
  16. CREATE DATABASE guestbook DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
  17. pair类型 C++
  18. 疫情问题网络舆情监测方法
  19. Linux(deepin) 解决 Anaconda 环境中 matplotlib 中文乱码问题
  20. 2021年2月社招面经分享_Java资深/高级开发

热门文章

  1. SCA可达性分析基础知识普及
  2. mysql数据库,使用substring函数截取字符串返回空问题
  3. 5分绩点转4分_4分绩点与百分制转换方法
  4. 图像数据集标注学习笔记
  5. 前端 CSS : 1# 纯 CSS 实现万圣节 toggle 控件
  6. Android 集成百度身份证识别
  7. POJ前面的题目算法思路【转】
  8. 【数位板常见问题】压感笔为什么没有压感了
  9. 【职场版】《漫漫邮子路(一)--走出你身处的“盒子”——朱斌》
  10. 牛客网试题+答案分析+大牛面试经验(12)