TCP基础题:音乐播放列表管理系统
需求描述
- 服务器端
- 创建一个 TCP 服务器,监听本地的 9999 端口,支持多个客户端连接。
- 维护一个音乐播放列表,每个音乐条目包含歌曲名称、歌手、时长等信息。
- 能够处理客户端的以下请求:
- 添加音乐到播放列表:接收客户端发送的 Music 对象,使用 ObjectInputStream 读取,并将其添加到播放列表中。
- 删除音乐:接收客户端发送的歌曲名称,使用 ObjectInputStream 读取,从播放列表中删除对应歌曲。
- 获取播放列表:将当前的播放列表封装成 MusicPlaylist 对象,使用 ObjectOutputStream 发送给客户端。
- 客户端
- 创建一个 TCP 客户端,连接到本地的 9999 端口。
- 可以向服务器发送添加音乐请求,创建 Music 对象并使用 ObjectOutputStream 发送。
- 可以向服务器发送删除音乐请求,将歌曲名称使用 ObjectOutputStream 发送。
- 可以向服务器发送获取播放列表请求,接收服务器返回的 MusicPlaylist 对象,使用 ObjectInputStream 读取并显示。
数据描述
- Music 类
- String songName:歌曲名称。
- String singer:歌手。
- int duration:歌曲时长(秒)。
- MusicPlaylist 类
- ArrayList<Music> musicList:音乐播放列表。
附加:修改歌单名字
Server和Client的Music,Data和MusicPlaylist类
music类
import java.io.Serializable;public class Music implements Serializable {private String songName;private String singer;private int duration;public Music(String songName, String singer, int duration) {this.songName = songName;this.singer = singer;this.duration = duration;}public String getSongName() {return songName;}public String getSinger() {return singer;}public int getDuration() {return duration;}public void setSongName(String songName) {this.songName=songName;}public void setSinger(String singer) {this.singer=singer;}public void setDuration(int duration) {this.duration=duration;}@Overridepublic String toString() {return "歌曲名称: " + songName + ", 歌手: " + singer + ", 时长: " + duration + " 秒";}
}
MusicPlaylist类
import java.io.Serializable;
import java.util.ArrayList;public class MusicPlaylist implements Serializable {private ArrayList<Music> musicList;public MusicPlaylist() {this.musicList = new ArrayList<>();}public ArrayList<Music> getMusicList() {return musicList;}public void addMusic(Music music) {musicList.add(music);}public void removeMusic(String songName) {musicList.removeIf(music -> music.getSongName().equals(songName));}public void modifyMusic(String songModify, String songNew){for (Music music : musicList) {if (music.getSongName().equals(songModify)){music.setSongName(songNew);}}}
}
Data类(Data类启到一个把用户操作封装的作用,便于数据的打包和传输,方便程序编写的使用)
import java.io.Serializable;public class Data implements Serializable {private String op;private String songName;private String songNew;private Music music;public Data() {}public Data(String op) {this.op=op;}public String getOp() {return op;}public void setOp(String op) {this.op=op;}public Music getMusic() {return music;}public void setMusic(Music music) {this.music=music;}public void setMusicName(String songName) {this.songName = songName;}public String getMusicName() {return songName;}public void setMusicNewName(String songNew) {this.songNew = songNew;}public String getMusicNewName() {return songNew;}
}
客户端ClientZJL:
import com.zb2.entity.Data;
import com.zb2.entity.Music;
import com.zb2.entity.MusicPlaylist;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;public class ClientZJL {public static void main(String[] args) throws IOException, ClassNotFoundException {Socket socket = new Socket("127.0.0.1", 9999);ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());String opWhat;String songDelete;String songModify;String songNew;String msg;Data op = new Data();// 添加音乐===============================================Music music = new Music("青花瓷", "周杰伦", 300);opWhat = "添加";//包装Dataop.setOp(opWhat);op.setMusic(music);//发送Dataoos.writeObject(op);//接收系统发回的信息msg = (String) ois.readObject();System.out.println(msg);//修改音乐===============================================opWhat = "修改";songModify = "青花瓷";songNew = "七里香";//包装Dataop.setOp(opWhat);op.setMusicName(songModify);op.setMusicNewName(songNew);//发送Dataoos.writeObject(op);//接收系统发回的信息msg = (String) ois.readObject();System.out.println(msg);//删除音乐===============================================opWhat = "删除";songDelete = "青花瓷";//包装Dataop.setOp(opWhat);op.setMusicName(songDelete);//发送Dataoos.writeObject(op);//接收系统发回的信息msg = (String) ois.readObject();System.out.println(msg);// 获取播放列表===============================================opWhat = "查看歌单";//包装Dataop.setOp(opWhat);//发送Dataoos.writeObject(op);//接收系统发回的歌单对象MusicPlaylist playlist = (MusicPlaylist) ois.readObject();//将歌单对象转换为集合并打印ArrayList<Music> musicList = playlist.getMusicList();for (Music m : musicList) {System.out.println(m);}}
}
服务端Server:
Server类
import com.zb2.entity.MusicPlaylist;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class Server {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(9999);System.out.println("服务器启动 端口:" + 9999);MusicPlaylist playlist = new MusicPlaylist();while (true) {Socket socket=serverSocket.accept();ServerThread serverThread = new ServerThread(socket, playlist);serverThread.start();}}
}
ServerThread类
import com.zb2.entity.Data;
import com.zb2.entity.MusicPlaylist;import java.io.*;
import java.net.Socket;public class ServerThread extends Thread {private Socket socket;private MusicPlaylist playlist;public ServerThread(Socket socket, MusicPlaylist playlist) {this.socket = socket;this.playlist = playlist;}@Overridepublic void run() {ObjectInputStream ois =null;ObjectOutputStream oos =null;try {ois=new ObjectInputStream(socket.getInputStream());oos=new ObjectOutputStream(socket.getOutputStream());Data op = new Data();op =(Data) ois.readObject();switch (op.getOp()) {case "添加":playlist.addMusic(op.getMusic());System.out.println("添加音乐: " + op.getMusic());oos.writeObject("添加成功!");break;case "删除":playlist.removeMusic(op.getMusicName());System.out.println("删除音乐: " + op.getMusicName());oos.writeObject("删除成功!");break;case "修改":playlist.modifyMusic(op.getMusicName(),op.getMusicNewName());System.out.println("修改音乐: " + op.getMusicName()+",为"+op.getMusicNewName());oos.writeObject("修改成功!");break;case "查看歌单":oos.writeObject(playlist);System.out.println("返回给客户端歌单");break;}} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}finally {try {oos.close();ois.close();socket.close();} catch (IOException e) {e.printStackTrace();}}}
}