我再写一个简单的聊天程序。
实现了客户端发消息,服务器端能受到,服务器端的客户端列表变化,客户端也能同步更新。
但是我不知道怎么实现客户端发送的消息,服务器端怎么转发给另外一个客户端,
希望各位好心的前辈高手们帮帮忙一下为我写的程序代码:
服务器端:import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;class client extends JFrame implements ActionListener
{
private JTextArea jtaList;
private TextArea jtaMessage;
private JTextField jtfSend;
private PrintWriter pw;
private String name;
private DataInputStream dis=null;
Thread glist=new Thread(new getlist());
Socket s=null;

public client(String name)
{
super(name);
this.name=name;
this.setSize(500,500);
this.setLocation(100,100);
this.setLayout(new FlowLayout());
jtaList=new JTextArea(20,10);
jtaMessage=new TextArea(20,32);
jtaMessage.setRows(20);
jtfSend=new JTextField(40);
this.add(jtaMessage);
this.add(jtaList);
this.add(jtfSend);
jtfSend.addActionListener(this);
this.addWindowListener(new winclose());
this.setVisible(true);
//Thread glist=new Thread(new getlist());
}

public void inint()
{
try
{
s=new Socket("localhost",5000);
pw=new PrintWriter(s.getOutputStream(),true);
//dis=new DataInputStream(s.getInputStream());
pw.println(name);
glist.start();
//glist.start();
}
catch(Exception e)
{
}
}

public void actionPerformed(ActionEvent e)
{
String str=this.jtfSend.getText().trim();
jtfSend.setText("");
this.jtaMessage.append(str+"\n\r");
pw.println(str);
}

class winclose extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}

public static void main(String args[])
{
// new client("bin").inint();
// getlists.start();
client c=new client("bin");
c.inint();
//c.getlist.start();
}

class getlist implements Runnable
{
public void run()
{
try
{

while(true)
{
dis=new DataInputStream(s.getInputStream());
String str=dis.readUTF();
jtaList.setText(str);
}
}
catch(Exception e)
{
System.out.println("get list error");
}
}
}
}客户端:import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.util.*;class serverlist extends JFrame implements ActionListener,TextListener
{
java.util.List<Client> clients = new ArrayList<Client>();
private JTextField jtState;
private TextArea jtlist;
private JButton jbclick;
private ServerSocket server;
//private Socket client;
private TextArea jtmessage;
private BufferedReader bf;
private DataOutputStream dos=null;
//private JLabel  jllist


public serverlist()
{
super("server list info");
this.setSize(400,400);
this.setLocation(100,100);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
jtlist=new TextArea("userlist"+"\r\n",6,35);
jtmessage=new TextArea("usermessage"+"\r\n",10,35);
jtState=new JTextField("no begin to listen");
jbclick=new JButton("click");
this.setLayout(new FlowLayout());
this.add(jtlist);
this.add(jbclick);

//this.jtlist.setEditable(true);
jbclick.addActionListener(this);
jtlist.addTextListener(this);

this.add(jtState);
this.add(jtmessage);
this.setVisible(true);

}

public void actionPerformed(ActionEvent e)
{

this.jtState.setText("begin to listen the port 5000");

}



public void textValueChanged(TextEvent e) 
{
String listname=this.jtlist.getText();
for(int i=0;i<clients.size();i++)
{
Client c=clients.get(i);
try
{
c.sendmessage(listname);
}
catch(IOException ee)
{
System.out.println(i+"erroer");
}
}
this.jtState.setText(Integer.toString(clients.size()));
}

public void init()
{
try
{
server=new ServerSocket(5000);

}
catch(Exception ee)
{
System.out.println("create serversocket error");
}
try
{
int i=0;
while(i<3)
{
Socket client=server.accept();
dos=new DataOutputStream(client.getOutputStream());
bf=new BufferedReader(new InputStreamReader(client.getInputStream()));
this.jtlist.append(bf.readLine()+"\r\n");
Client c=new Client(client);
new Thread(c).start();
clients.add(c);
i++;
}
}
catch(Exception eee)
{
System.out.println("i don't how to do it");
}
}

class Client implements Runnable
{
Socket clients;
private BufferedReader brd;
private DataOutputStream dos=null;

public Client(Socket s)
{
try
{
clients=s;
dos=new DataOutputStream(clients.getOutputStream());
}
catch(Exception e)
{
}
}

public void sendmessage(String str) throws IOException
{
try
{

dos.writeUTF(str);
}
catch(IOException eeee)
{
}
}

public void run()
{
try
{
while(true)
{
brd=new BufferedReader(new InputStreamReader(clients.getInputStream()));
jtmessage.append(bf.readLine()+"\r\n");
}
}
catch(Exception e)
{
}
}

}

public static void main(String [] args)
{
new serverlist().init();
}
}


解决方案 »

  1.   

    初次发帖,可能标题没有写好,想求教关于socket方面的问题
      

  2.   

    要做完这个程序, 工作量是不少, 而且如果是去改你的程序, 在你的思路上再去完善, 更难, 因为首先要自己理解这个题的意思,会写, 然后还要去学习你的逻辑思维, 顺着你的思路走,可想而知。只能提些改进的建议:
    1. 不推荐使用TCP来做聊天的连接, 使用UDP更合适, 因为TCP是保持连接的, 比较消耗资源,
       而聊天的内容却不必要求这么严格。
    2. TCP连接用来如处理聊天程序中的传文件等功能时使用, 即TCP与UDP结合使用。3. 当某一客户端连接上服务器时, 从服务器上下载好友信息。
    4. 服务器还要主动的把此客户端上线的消息通知他的好友。
    5. 如果要与某人私聊, 直接发送UDP消息给对方, 不需要通过服务器。这样做有很多好处, 
       减轻了服务器的负载。
    6. 群聊时才通过服务器转发或者客户端直接也保存了群的客户的状态, 直接用UDP发送给他们(这个问题我想得不是很清楚, 希望懂的更正补充)。UDP连接有一个好处, 不用对每一个客户端都开一个线程来处理, 也减少了资源的占用。楼下的继续更正, 被充, 完善。
      

  3.   

    补充一下:以前一开始的时候我的思路也与上面的几位说的差不多, 不过后来在CSDN看一大虾说过, 如果每遇到一个连接, 就开一个线程来处理, 那就是小孩子的玩法。 印象深刻!!
      

  4.   

    我也曾想过用udp,但是问了下群里的高手,他们说,如果用udp,确实要简单些,但是由于国家要求服务器端必须要保留聊天记录,所以都改为用udp
      

  5.   

    至于聊天记录, 你可以在本地保存, 同时再上传一份到服务器就行了。如果你仔细一些, 就会发现QQ也是用UDP来聊天, TCP来传文件的。因为我用MIM来上QQ, 由于中间使用了第三方的服务器, 所以消息的延迟比直接用腾讯的QQ延迟要大得多, 很容易发现这个问题。
      

  6.   

    给你个例子
    1.Server
    package sockettester;import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Enumeration;
    import java.util.Hashtable;public final class ChatServer implements Serializable {
    private static final long serialVersionUID = -7120409661661920128L;
    private static final int port = 14444;
    private static ChatServer instance = new ChatServer();

    private Hashtable<Socket, ObjectOutputStream> clients;
    private Object clientsLock;

    public static void main(String[] args) {
    ChatServer logRegServer = ChatServer.getInstance();
    logRegServer.startService();
        } public static synchronized ChatServer getInstance() {
    return instance;
    }

    protected ChatServer() {
    this.clients = new Hashtable<Socket, ObjectOutputStream>();
    this.clientsLock = new Object();
    }

    public void startService() {
    ServerSocket serverSocket = null;
    Socket clientSocket; try {
    serverSocket = new ServerSocket(port);
    while(true) {
    clientSocket = serverSocket.accept();
    System.out.println("[" + clientSocket.toString() + "] login...");
    new ServerThread(clientSocket).start();
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    clientSocket = null;
    if(serverSocket != null) {
    serverSocket.close();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

    private class ServerThread extends Thread {
    private Socket clientSocket; public ServerThread(Socket socket) {
    this.clientSocket = socket;
    }

    public void run() {
    ObjectInputStream socketIn = null;
    ObjectOutputStream socketOut = null;
    try {
    socketIn = new ObjectInputStream(this.clientSocket.getInputStream());
    socketOut = new ObjectOutputStream(this.clientSocket.getOutputStream());
    synchronized(ChatServer.this.clientsLock) {
    if(!ChatServer.this.clients.containsKey(clientSocket)) {
    ChatServer.this.clients.put(this.clientSocket, socketOut);
    }
    }
    Object readingObject;
    String message;
    Enumeration<Socket> allKeys;
    Socket otherSocket;
    ObjectOutputStream otherSocketOut;
    while ((readingObject = socketIn.readObject()) != null) {
    if (readingObject instanceof String) {
    message = (String)readingObject;
    System.out.println("Message incoming:[" + message + "]\n\tfrom " + this.clientSocket.toString());
    synchronized(ChatServer.this.clientsLock) {
    allKeys = ChatServer.this.clients.keys();
    while(allKeys.hasMoreElements()) {
    otherSocket = allKeys.nextElement();
    //if(!otherSocket.equals(this.clientSocket)) {
    otherSocketOut = ChatServer.this.clients.get(otherSocket);
    otherSocketOut.writeObject(readingObject);
    otherSocketOut.flush();
    //}
    Thread.sleep(1);
    }
    }
    }
    Thread.sleep(1);
    }
    } catch (Exception e) {
    try {
    synchronized(ChatServer.this.clientsLock) {
    this.clientSocket.close();
    ChatServer.this.clients.remove(this.clientSocket);
    }
    } catch (Exception ee) {
    ee.printStackTrace();
    }
    }
    }
    }
    }
    2.Client
    package sockettester;import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.Socket;import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;public final class ChatClient extends JFrame {
    private static final long serialVersionUID = 2432611980549259658L; private static final int serverPort = 14444; private static final String serverHost = "127.0.0.1"; private class ReceiveThread extends Thread {
    private Socket socket = null; private ObjectInputStream socketIn = null; private ObjectOutputStream socketOut = null; private boolean isConnected; public ReceiveThread() {
    this.isConnected = false;
    } public synchronized boolean connectToServer(int port, String host) {
    if (!this.isConnected) {
    try {
    this.socket = new Socket(host, port);
    this.socketOut = new ObjectOutputStream(this.socket
    .getOutputStream());
    this.socketIn = new ObjectInputStream(this.socket
    .getInputStream());
    this.isConnected = true;
    } catch (Exception e) {
    this.isConnected = false;
    e.printStackTrace();
    try {
    if (this.socketOut != null) {
    this.socketOut.close();
    }
    if (this.socketIn != null) {
    this.socketIn.close();
    }
    if (this.socket != null) {
    this.socket.close();
    }
    } catch (Exception ee) {
    ee.printStackTrace();
    } finally {
    this.socket = null;
    this.socketIn = null;
    this.socketOut = null;
    }
    }
    }
    return this.isConnected;
    } public synchronized void disconnectServer() {
    if (this.isConnected) {
    try {
    this.socketOut.close();
    this.socketIn.close();
    this.socket.close();
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    this.socket = null;
    this.socketIn = null;
    this.socketOut = null;
    this.isConnected = false;
    }
    }
    } public synchronized boolean sendMessage(String message) {
    boolean retVal = false; if (this.isConnected) {
    try {
    this.socketOut.writeObject(message);
    this.socketOut.flush();
    retVal = true;
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    return retVal;
    } public void run() {
    try {
    Object readingObject;
    while (true) {
    readingObject = this.socketIn.readObject();
    if (readingObject instanceof String) {
    ChatClient.this
    .displayMessage((String) readingObject);
    }
    sleep(1);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    } protected void finalize() {
    this.disconnectServer();
    }
    } private ReceiveThread receiveThread; private JTextArea chatArea; public ChatClient() {
    this.receiveThread = new ReceiveThread();
    this.add(chatPane(), BorderLayout.CENTER);
    this.pack();
    this.setTitle("example");
    this.setSize(400, 300);
    this.setLocation(100, 20);
    this.setVisible(true);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    } public boolean start() {
    if (this.receiveThread.connectToServer(serverPort, serverHost)) {
    this.receiveThread.start();
    }
    return false;
    } protected void displayMessage(String msg) {
    this.chatArea.append(msg + '\n');
    } private JPanel chatPane() {
    JPanel chatP = new JPanel();
    chatP.setLayout(new BorderLayout()); final JTextField chatTF = new JTextField(); /** 为聊天信息输入框添加回车事件 */
    chatTF.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    ChatClient.this.receiveThread
    .sendMessage(chatTF.getText());
    chatTF.setText("");
    }
    }); /** 聊天显示区 */
    this.chatArea = new JTextArea();
    this.chatArea.setEditable(false); chatP.add(this.chatArea, BorderLayout.CENTER);
    chatP.add(chatTF, BorderLayout.SOUTH); return chatP;
    }

    public static void main(String[] args){
    ChatClient logRegClient = new ChatClient();
    logRegClient.start();
    }}
      

  7.   

    这样解决:
    服务器端维护一个地址和成员id的列表,也就是把每个成员的 id和对应ip地址存放在一个列表里,
    客户端向另一个客户端发信息时候,信息头部包括一个接收信息客户端的id,这样服务器端受到信息后,
    根据信息头部的id在地址列表里找到对应的ip地址,然后就可以把信息转到对应的客户端了。