我再写一个简单的聊天程序。
实现了客户端发消息,服务器端能受到,服务器端的客户端列表变化,客户端也能同步更新。
但是我不知道怎么实现客户端发送的消息,服务器端怎么转发给另外一个客户端,
希望各位好心的前辈高手们帮帮忙一下为我写的程序代码:
服务器端: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();
}
}
实现了客户端发消息,服务器端能受到,服务器端的客户端列表变化,客户端也能同步更新。
但是我不知道怎么实现客户端发送的消息,服务器端怎么转发给另外一个客户端,
希望各位好心的前辈高手们帮帮忙一下为我写的程序代码:
服务器端: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. 不推荐使用TCP来做聊天的连接, 使用UDP更合适, 因为TCP是保持连接的, 比较消耗资源,
而聊天的内容却不必要求这么严格。
2. TCP连接用来如处理聊天程序中的传文件等功能时使用, 即TCP与UDP结合使用。3. 当某一客户端连接上服务器时, 从服务器上下载好友信息。
4. 服务器还要主动的把此客户端上线的消息通知他的好友。
5. 如果要与某人私聊, 直接发送UDP消息给对方, 不需要通过服务器。这样做有很多好处,
减轻了服务器的负载。
6. 群聊时才通过服务器转发或者客户端直接也保存了群的客户的状态, 直接用UDP发送给他们(这个问题我想得不是很清楚, 希望懂的更正补充)。UDP连接有一个好处, 不用对每一个客户端都开一个线程来处理, 也减少了资源的占用。楼下的继续更正, 被充, 完善。
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();
}}
服务器端维护一个地址和成员id的列表,也就是把每个成员的 id和对应ip地址存放在一个列表里,
客户端向另一个客户端发信息时候,信息头部包括一个接收信息客户端的id,这样服务器端受到信息后,
根据信息头部的id在地址列表里找到对应的ip地址,然后就可以把信息转到对应的客户端了。