我尝试使用多个客户端和单个服务器编写类似聊天的应用程序。想法:客户端将String发送到服务器,服务器使用它并返回客户端对象(只有发送字符串的客户端才能收到答案!)。
问题:单个客户端运行良好。运行第二个客户端会产生麻烦:客户端2收到客户端1的答案,在第一次接听后,两个客户端都无法发送任何内容。
换句话说,我需要帮助。
这是代码: 服务器:
public class serverWindow extends JFrame {
private JPanel contentPane;
private static JTextField tfAddition;
static JTextPane tp;
// connection stuff
static ServerSocket ss = null;
static Socket soc = null;
static DataInputStream din;
static ObjectOutputStream obout;
static int port = 1255;
public static void main(String[] args) throws IOException
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
serverWindow frame = new serverWindow();
frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
try
{
ss = new ServerSocket(port);
while(true)
{
try
{
soc = ss.accept();
echoThread X = new echoThread(soc, tp);
X.start();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
ss.close();
}
}
/**
* Create the frame.
*/
public serverWindow() {
setTitle("Server");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 11, 414, 183);
contentPane.add(scrollPane);
tp = new JTextPane();
tp.setEditable(false);
scrollPane.setViewportView(tp);
}
}
echoThread:
public class echoThread extends Thread
{
protected Socket soc;
public JTextPane tp;
static DataInputStream din = null;
static ObjectOutputStream obout = null;
public echoThread(Socket soc, JTextPane tp)
{
this.soc = soc;
this.tp = tp;
}
public void run()
{
try
{
din = new DataInputStream(this.soc.getInputStream());
obout = new ObjectOutputStream(soc.getOutputStream());
while(true)
{
String message = din.readUTF();
tp.setText(tp.getText().trim() + "\n" + message);
Response res = new Response(message, message.length());
obout.writeObject(res);
obout.flush();
}
}
catch(Exception ex)
{
ex.printStackTrace();
return;
}
finally
{
try
{
soc.close();
din.close();
obout.close();
}
catch(Exception ex)
{
ex.printStackTrace();
return;
}
}
}
}
客户端:
public class clientW extends JFrame {
private JPanel contentPane;
private JTextField textField;
private static JTextPane textPane;
// sockets
static Socket soc = null;
static ObjectInputStream obin = null;
static DataOutputStream dout = null;
static int port = 1255;
static String host = "localhost";
public static void main(String[] args) throws IOException
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
clientW frame = new clientW();
frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
try
{
try
{
soc = new Socket(host, port);
dout = new DataOutputStream(soc.getOutputStream());
obin = new ObjectInputStream(soc.getInputStream());
while(true)
{
Response res = (Response) obin.readObject();
textPane.setText(textPane.getText().trim() + "\n" + res.combineText());
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
soc.close();
obin.close();
dout.close();
}
}
public clientW() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnNewButton = new JButton("send");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0)
{
try
{
dout.writeUTF(textField.getText().trim());
dout.flush();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
});
btnNewButton.setBounds(335, 227, 89, 23);
contentPane.add(btnNewButton);
textField = new JTextField();
textField.setBounds(10, 227, 315, 21);
contentPane.add(textField);
textField.setColumns(10);
textPane = new JTextPane();
textPane.setEditable(false);
textPane.setBounds(10, 11, 414, 205);
contentPane.add(textPane);
}
}
答案 0 :(得分:1)
din和obout被声明为静态变量,因此它们在所有客户端之间共享。这可以通过在没有关键字static的情况下声明din和obout来纠正。这样可以解决吗?
答案 1 :(得分:1)
您将echoThread
中的流定义为静态,这意味着该类的所有实例都将共享这些对象。因此,当第二个echoThread
实例启动时,它会覆盖第一个实例的流,因此一个套接字的流将丢失。如果将定义更改为:
private DataInputStream din = null;
private ObjectOutputStream obout = null;
它似乎按照你描述的那样工作。