所以我一直在努力制作一个节目。该计划有点基础。我想用发送图片制作聊天程序。所以现在的问题是我现在有两个服务器和两个客户端。一个用于聊天,另一个用于图片。我想将它们组合到一个服务器上,以使代码更少,更有用,但我不知道它是否可行。否则我需要一个提示方法如何继续这个,因为现在我卡住了。所以我的服务器看起来像这样。是否可能?


服务器聊天:


 公共服务器( int port){
 this(port,null);
 }

 public Server(int port,ServerGUI sg){
 // GUI是否
 this.sg = sg;
 //端口
 this.port = port;
 //显示hh:mm:ss
 sdf = new SimpleDateFormat(“HH:mm:ss”);
 // ClientList列表
 al = new ArrayList< ClientThread>();
 }

 public void start(){
 keepGoing = true;
 / *创建套接字服务器并等待连接请求* /
试试
 {
 //服务器使用的套接字
 ServerSocket serverSocket = new ServerSocket(port);

 //无限循环等待连接
而(keepGoing)
 {
 //格式化消息说我们正在等待
 display(“服务器等待端口上的客户端”+端口+“。”);

套接字socket = serverSocket.accept(); //接受连接
 //如果我被要求停止
如果(keepGoing!)
打破;
 ClientThread t = new ClientThread(socket); //制作一个线程
 al.add(T); //将它保存在ArrayList
 t.start();
 }
 //我被要求停止
试试{
 serverSocket.close();
 for(int i = 0; i< al.size(); ++ i){
 ClientThread tc = al.get(i);
试试{
 tc.sInput.close();
 tc.sOutput.close();
 tc.socket.close();
 }
 catch(IOException ioE){
 //我做的不多
 }
 }
 }
 catch(例外e){
 display(“关闭服务器和客户端的例外:”+ e);
 }
 }
 //事情变坏
 catch(IOException e){
 String msg = sdf.format(new Date())+“新ServerSocket上的异常:”+ e +“\ n”;
显示器(MSG);
 }
 }

类ClientThread扩展线程{
 //套接字在哪里听/说
套接字插座;
 ObjectInputStream sInput;
 ObjectOutputStream sOutput;
 //我唯一的id(更容易断开连接)
 int id;
 //客户的用户名
 String username;
 //将收到的唯一消息类型
消息cm;
 //我连接的日期
字符串日期;

 // Constructore
 ClientThread(套接字套接字){
 //一个唯一的id
 id = ++ uniqueId;
 this.socket = socket;
 / *创建数据流* /
 System.out.println(“线程试图创建对象输入/输出流”);
尝试
 {
 //首先创建输出
 sOutput = new ObjectOutputStream(socket.getOutputStream());
 sInput = new ObjectInputStream(socket.getInputStream());
 //读取用户名
 username =(String)sInput.readObject();
 display(username +“just connected。”);
 }
 catch(IOException e){
 display(“异常创建新的输入/输出流:”+ e);
返回;
 }
 //必须捕获ClassNotFoundException
 //但我读了一个字符串,我相信它会起作用
 catch(ClassNotFoundException e){
 }
 date = new Date()。toString()+“\ n”;
 }



 图片服务器


 公共类GreetingServer {

 public final static int SOCKET_PORT = 13267; //你可以改变这个
 public final static String FILE_TO_SEND =“C:/Users/Barry/Desktop/Duck.jpg”; //你可以改变这个

 public static void main(String [] args)抛出IOException {
 FileInputStream fis = null;
 BufferedInputStream bis = null;
 OutputStream os = null;
 ServerSocket servsock = null;
 Socket sock = null;
试试{
 servsock = new ServerSocket(SOCKET_PORT);
而(真){
的System.out.println( “请稍候”);
试试{
 sock = servsock.accept();
 System.out.println(“Accepted connection:”+ sock);
 //发送文件
文件myFile =新文件(FILE_TO_SEND);
 byte [] mybytearray = new byte [(int)myFile.length()];
 fis = new FileInputStream(myFile);
 bis = new BufferedInputStream(fis);
 bis.read(mybytearray,0,mybytearray.length);
 os = sock.getOutputStream();
 System.out.println(“发送”+ FILE_TO_SEND +“(”+ mybytearray.length +“bytes)”);
 os.write(mybytearray,0,mybytearray.length);
 os.flush();
的System.out.println( “完成”。);
 }
终于{
 if(bis!= null)bis.close();
 if(os!= null)os.close();
 if(sock!= null)sock.close();
 }
 }
 }
终于{
 if(servsock!= null)servsock.close();
 }
 }
}
 代码>


答案 0 :(得分:0)
要将两种数据放在同一个套接字上,您需要在某种程度上区分这两种数据。由于您无论如何都在使用对象输入/输出流,因此使用这两个类似乎是区分的好方法。使用isAssignableFrom找出每个对象是什么。
public static class ChatText implements Serializable {
private String text;
/**
* Get the value of text
*
* @return the value of text
*/
public String getText() {
return text;
}
/**
* Set the value of text
*
* @param text new value of text
*/
public void setText(String text) {
this.text = text;
}
}
...
public static class PictureData implements Serializable {
private byte[] data;
/**
* Get the value of data
*
* @return the value of data
*/
public byte[] getData() {
return data;
}
/**
* Set the value of data
*
* @param data new value of data
*/
public void setData(byte[] data) {
this.data = data;
}
}
...
public static void main(String[] args) {
try {
// Server implemented here
ExecutorService es = Executors.newFixedThreadPool(4);
ServerSocket ss = new ServerSocket(1234);
es.submit(() -> {
while (true) {
Socket s = ss.accept();
es.submit(() -> {
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
while (true) {
Object o = ois.readObject();
if (PictureData.class.isAssignableFrom(o.getClass())) {
PictureData pd = (PictureData) o;
System.out.println("got picture:" + Arrays.toString(pd.getData()));
// Do something with picture here.
} else if (ChatText.class.isAssignableFrom(o.getClass())) {
ChatText ct = (ChatText) o;
System.out.println("got text:" + ct.getText());
// Do something with chat here.
}
}
});
}
});
// Client implemented here, just for Testing
Socket s = new Socket("localhost", 1234);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ChatText ct = new ChatText();
ct.setText("first chat");
oos.writeObject(ct);
//In a real client, the next three lines would be in a separate
// class/function attached to some event handler.
PictureData pd = new PictureData();
pd.setData(new byte[]{1, 2, 3, 4});
oos.writeObject(pd);
Thread.sleep(2000); // ugly hack to make sure server doesn't close too early, for testing only
es.shutdownNow();
s.close();
ss.close();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
真正的客户端会将我标记的部分放在main中,并从某个事件处理程序运行它。更像这样:
public class MyClient extends JFrame {
MyClient(String host, int port) {
try {
Socket s= new Socket(host,port);
JButton myButton = new JButton("Send Picture");
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
myButton.addActionListener(e -> {
try {
// Copy of code from previous example.
PictureData pd = new PictureData();
pd.setData(new byte[]{1, 2, 3, 4});
oos.writeObject(pd);
} catch (IOException ex) {
ex.printStackTrace();
}
});
add(myButton);
pack();
setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> new MyClient("localhost",1234));
}
}