100分求助Socket网络编程

wangdong20 2012-07-10 02:33:11
现在想做一个类似于QQ群功能程序,做的过程遇到很多问题
Server类只需要实现接受每个client类的传出的信息,并且打印在自己的信息板上,
然后将接受的信息发送给每个client
也就是说,每个client能看到彼此发送的信息,功能类似于QQ群
client的功能一是打印自己输出的信息,二是接受Server传过来的信息,打印出来
初学网络编程,欢迎拍砖
下面是代码
Server 类

package ex30;

import javax.swing.*;

import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;

public class Ex30_13Server extends JFrame{
private JTextArea jtaServer = new JTextArea();
private BufferedReader input;
private String sendMessage = "";
private ArrayList<Socket> socketArray = new ArrayList<Socket>();

public Ex30_13Server(){
jtaServer.setEditable(false);
add(new JScrollPane(jtaServer));
setTitle("MultiThreadServer");
setSize(700, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

try{
ServerSocket serverSocket = new ServerSocket(8000);

while(true){
Socket socket = serverSocket.accept();
InetAddress inetAddress = socket.getInetAddress();
jtaServer.append(inetAddress.getHostName() + " connected " + new Date());
socketArray.add(socket);

MutiUser mu = new MutiUser(socket);
mu.start();
}
}
catch(Exception ex){
ex.printStackTrace();
}
}

// Define the thread class for send message
class SendTask implements Runnable{
public void run(){
try{
while(true){
if(!sendMessage.isEmpty()){
for(Socket socket : socketArray){ // 将接受的信息输出到每个客户端上
PrintWriter outputToEachClient = new PrintWriter(socket.getOutputStream());
outputToEachClient.println(sendMessage);
}
sendMessage = "";
}
}
}
catch(Exception ex){
ex.printStackTrace();
}

}
}


// Define the thread class for receive message
class ReceiveTask implements Runnable{
public void run(){
try{
while(true){
String receiveMessage = input.readLine();
if(!receiveMessage.isEmpty()){
jtaServer.append(receiveMessage + "\n");
sendMessage = receiveMessage;
}

}
}
catch(IOException ex){
ex.printStackTrace();
}
}
}

class MutiUser extends Thread{
private Socket server;

public MutiUser(Socket server){
this.server = server;
}

public void run(){
try{
input = new BufferedReader(new InputStreamReader(server.getInputStream()));
new Thread(new SendTask()).start();
new Thread(new ReceiveTask()).start();
}
catch(Exception ex){
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Server();
}

}


client类

package ex30;

import javax.swing.*;

import ex30.Ex30_12Client.ReceiveTask;
import ex30.Ex30_12Client.SendTask;

import java.io.*;

import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class Ex30_13Client extends JFrame{
private JLabel jlblName = new JLabel("Name");
private JLabel jlblText = new JLabel("Enter text");
private JTextField jtfName = new JTextField();
private JTextField jtfText = new JTextField();
private JTextArea jtaClient = new JTextArea();
private PrintWriter output;
private BufferedReader input;
private String sendMessage = "";

public Ex30_13Client(){
JPanel panel1 = new JPanel(new GridLayout(2, 1));
panel1.add(jlblName);
panel1.add(jlblText);

JPanel panel2 = new JPanel(new GridLayout(2, 1));
panel2.add(jtfName);
panel2.add(jtfText);

JPanel panel = new JPanel(new BorderLayout());
panel.add(panel1, BorderLayout.WEST);
panel.add(panel2, BorderLayout.CENTER);

setLayout(new BorderLayout());
add(panel, BorderLayout.NORTH);
add(jtaClient, BorderLayout.CENTER);
jtaClient.setEditable(false);

setTitle("Ex30_13Client");;
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);


jtfText.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER){
String text = jtfText.getText();

if(!text.isEmpty()){
sendMessage = jtfName.getText() + ":" + text;
output.println(sendMessage);
output.flush();
System.out.println(sendMessage);
jtfText.setText("");
}
}
}
});

try{
Socket socket = new Socket("localhost", 8000);
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new Thread(new SendTask()).start();
new Thread(new ReceiveTask()).start();
}
catch (Exception ex){
ex.printStackTrace();
}

}

class SendTask implements Runnable{
public void run(){
try{
while(true){
if(!sendMessage.isEmpty()){
jtaClient.append(sendMessage + "\n");
sendMessage = "";
}
}
}
catch(Exception ex){
ex.printStackTrace();
}
}
}

class ReceiveTask implements Runnable{
public void run(){
try{
while(true){
String receiveMessage = input.readLine();
jtaClient.append(receiveMessage + "\n");
}
}
catch(Exception ex){
ex.printStackTrace();
}
}
}



public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Client();
}

}
...全文
263 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
yktd26 2012-07-11
  • 打赏
  • 举报
回复
只是为了服务监听放在单独的线程
wangdong20 2012-07-10
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
闲来无事帮你写了写,服务器端改得多了点,客户端基本没动,能完成你要的功能
服务器端

Java code

package ex30;

import javax.swing.*;


import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;
import……
[/Quote]
有点不理解为什么Server类也要实现Runnable接口
wangdong20 2012-07-10
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
闲来无事帮你写了写,服务器端改得多了点,客户端基本没动,能完成你要的功能
服务器端

Java code

package ex30;

import javax.swing.*;


import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;
import……
[/Quote]
膜拜 大牛的回复
杀手 2012-07-10
  • 打赏
  • 举报
回复
楼上的是正确的,改了几次楼主的代码,发现楼主对对象的使用存在些问题,可以学习
yktd26 2012-07-10
  • 打赏
  • 举报
回复
闲来无事帮你写了写,服务器端改得多了点,客户端基本没动,能完成你要的功能
服务器端
package ex30;

import javax.swing.*;


import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Ex30_13Server extends JFrame implements Runnable{
private JTextArea jtaServer = new JTextArea();
private BufferedReader input;
private String sendMessage = "";
private ConcurrentLinkedQueue<String> messageQueue = null;
private ArrayList<Socket> socketArray = new ArrayList<Socket>();

public Ex30_13Server(){
jtaServer.setEditable(false);
add(new JScrollPane(jtaServer));
setTitle("MultiThreadServer");
setSize(700, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.messageQueue = new ConcurrentLinkedQueue<String>();
new Thread(this).start();
}

@Override
public void run() {
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(8000);
new Thread(new broadcaster()).start();
while(true){
Socket socket = serverSocket.accept();
InetAddress inetAddress = socket.getInetAddress();
synchronized (socketArray){
socketArray.add(socket);
}
new Thread( new UserInput(socket)).start();
synchronized (jtaServer) {
jtaServer.append(inetAddress.getHostName() + " connected " + new Date()+ "\n");
}
}

} catch(Exception ex){
ex.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

class broadcaster implements Runnable{

@Override
public void run() {
while (true){
if (!messageQueue.isEmpty()){
synchronized (socketArray){
try {
String message = messageQueue.poll();
for(Socket socket : socketArray){ // 将接受的信息输出到每个客户端上
PrintWriter outputToEachClient = new PrintWriter(socket.getOutputStream());
outputToEachClient.println(message);
outputToEachClient.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}

class UserInput implements Runnable {
private Socket socket;

public UserInput(Socket socket){
this.socket = socket;
}

@Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine = null;
while (true){
while ((inputLine = in.readLine()) != null) {
messageQueue.add(inputLine);
jtaServer.append(inputLine+"\n");
}
}
} catch (Exception e) {
//e.printStackTrace();
} finally {
try {
socket.close();
synchronized (socketArray){
socketArray.remove(socket);
}
} catch (IOException e1) {
System.out.println("Can not close socket");
}
}
}
}

public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Server();
}
}

客户端
package ex30;

import javax.swing.*;

import java.io.*;

import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class Ex30_13Client extends JFrame{
private JLabel jlblName = new JLabel("Name");
private JLabel jlblText = new JLabel("Enter text");
private JTextField jtfName = new JTextField();
private JTextField jtfText = new JTextField();
private JTextArea jtaClient = new JTextArea();
private PrintWriter output;
private BufferedReader input;
private String sendMessage = "";

public Ex30_13Client(){
JPanel panel1 = new JPanel(new GridLayout(2, 1));
panel1.add(jlblName);
panel1.add(jlblText);

JPanel panel2 = new JPanel(new GridLayout(2, 1));
panel2.add(jtfName);
panel2.add(jtfText);

JPanel panel = new JPanel(new BorderLayout());
panel.add(panel1, BorderLayout.WEST);
panel.add(panel2, BorderLayout.CENTER);

setLayout(new BorderLayout());
add(panel, BorderLayout.NORTH);
add(jtaClient, BorderLayout.CENTER);
jtaClient.setEditable(false);

setTitle("Ex30_13Client");;
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);


jtfText.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER){
String text = jtfText.getText();

if(!text.isEmpty()){
sendMessage = jtfName.getText() + ":" + text;
output.println(sendMessage);
output.flush();
System.out.println(sendMessage);
jtfText.setText("");
}
}
}
});

try{
Socket socket = new Socket("localhost", 8000);
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new Thread(new ReceiveTask()).start();
}
catch (Exception ex){
ex.printStackTrace();
}
}

class ReceiveTask implements Runnable{
public void run(){
try{
String inputLine = null;
while (true){
while ((inputLine = input.readLine()) != null) {
jtaClient.append(inputLine+"\n");
}
}
}
catch(Exception ex){
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Client();
}

}
yktd26 2012-07-10
  • 打赏
  • 举报
回复
闲来无事帮你改了改,服务器端改得多点,客户端基本没动,能完成你要的功能了

package ex30;

import javax.swing.*;


import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Ex30_13Server extends JFrame implements Runnable{
private JTextArea jtaServer = new JTextArea();
private BufferedReader input;
private String sendMessage = "";
private ConcurrentLinkedQueue<String> messageQueue = null;
private ArrayList<Socket> socketArray = new ArrayList<Socket>();

public Ex30_13Server(){
jtaServer.setEditable(false);
add(new JScrollPane(jtaServer));
setTitle("MultiThreadServer");
setSize(700, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.messageQueue = new ConcurrentLinkedQueue<String>();
new Thread(this).start();
}

@Override
public void run() {
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(8000);
new Thread(new broadcaster()).start();
while(true){
Socket socket = serverSocket.accept();
InetAddress inetAddress = socket.getInetAddress();
synchronized (socketArray){
socketArray.add(socket);
}
new Thread( new UserInput(socket)).start();
synchronized (jtaServer) {
jtaServer.append(inetAddress.getHostName() + " connected " + new Date()+ "\n");
}
}

} catch(Exception ex){
ex.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

class broadcaster implements Runnable{

@Override
public void run() {
while (true){
if (!messageQueue.isEmpty()){
synchronized (socketArray){
try {
String message = messageQueue.poll();
for(Socket socket : socketArray){ // 将接受的信息输出到每个客户端上
PrintWriter outputToEachClient = new PrintWriter(socket.getOutputStream());
outputToEachClient.println(message);
outputToEachClient.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}

class UserInput implements Runnable {
private Socket socket;

public UserInput(Socket socket){
this.socket = socket;
}

@Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine = null;
while (true){
while ((inputLine = in.readLine()) != null) {
messageQueue.add(inputLine);
jtaServer.append(inputLine+"\n");
}
}
} catch (Exception e) {
//e.printStackTrace();
} finally {
try {
socket.close();
synchronized (socketArray){
socketArray.remove(socket);
}
} catch (IOException e1) {
System.out.println("Can not close socket");
}
}
}
}

public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Server();
}
}


package ex30;

import javax.swing.*;

import java.io.*;

import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class Ex30_13Client extends JFrame{
private JLabel jlblName = new JLabel("Name");
private JLabel jlblText = new JLabel("Enter text");
private JTextField jtfName = new JTextField();
private JTextField jtfText = new JTextField();
private JTextArea jtaClient = new JTextArea();
private PrintWriter output;
private BufferedReader input;
private String sendMessage = "";

public Ex30_13Client(){
JPanel panel1 = new JPanel(new GridLayout(2, 1));
panel1.add(jlblName);
panel1.add(jlblText);

JPanel panel2 = new JPanel(new GridLayout(2, 1));
panel2.add(jtfName);
panel2.add(jtfText);

JPanel panel = new JPanel(new BorderLayout());
panel.add(panel1, BorderLayout.WEST);
panel.add(panel2, BorderLayout.CENTER);

setLayout(new BorderLayout());
add(panel, BorderLayout.NORTH);
add(jtaClient, BorderLayout.CENTER);
jtaClient.setEditable(false);

setTitle("Ex30_13Client");;
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);


jtfText.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER){
String text = jtfText.getText();

if(!text.isEmpty()){
sendMessage = jtfName.getText() + ":" + text;
output.println(sendMessage);
output.flush();
System.out.println(sendMessage);
jtfText.setText("");
}
}
}
});

try{
Socket socket = new Socket("localhost", 8000);
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new Thread(new ReceiveTask()).start();
}
catch (Exception ex){
ex.printStackTrace();
}
}

class ReceiveTask implements Runnable{
public void run(){
try{
String inputLine = null;
while (true){
while ((inputLine = input.readLine()) != null) {
jtaClient.append(inputLine+"\n");
}
}
}
catch(Exception ex){
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Client();
}

}


wangdong20 2012-07-10
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
server 类改一下,关键是整体设计不太好



Java code


package ex40;

import javax.swing.*;

import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;

public class Ex30_13……
[/Quote]
太棒了,现在client传出的信息server可以都接受到
但是还有一个问题,就是server接受的信息,
不知道是没有发送给client,还是client没接收到
我原本是想用每一个客户端创建的Socket,添加到socketArray,
然后接收到后通过每个socket 传给各个client
就差这一步了,我已经想了很久了,恳求楼上再看看是怎么回事
杀手 2012-07-10
  • 打赏
  • 举报
回复
server 类改一下,关键是整体设计不太好



package ex40;

import javax.swing.*;

import java.io.*;

import java.io.IOException;
import java.net.*;
import java.util.*;

public class Ex30_13Server extends JFrame {
private JTextArea jtaServer = new JTextArea();
private String sendMessage = "";
private ArrayList<Socket> socketArray = new ArrayList<Socket>();

public Ex30_13Server() {
jtaServer.setEditable(false);
add(new JScrollPane(jtaServer));
setTitle("MultiThreadServer");
setSize(700, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

try {
ServerSocket serverSocket = new ServerSocket(8000);

while (true) {
Socket socket = serverSocket.accept();
InetAddress inetAddress = socket.getInetAddress();
jtaServer.append(inetAddress.getHostName() + " connected "
+ new Date());
socketArray.add(socket);

MutiUser mu = new MutiUser(socket);
mu.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}

// Define the thread class for send message
class SendTask implements Runnable {
private MutiUser mu;

public SendTask(MutiUser mu) {
this.mu=mu;
}

public void run() {
try {
while (true) {
if (!sendMessage.isEmpty()) {
for (Socket socket : socketArray) { // 将接受的信息输出到每个客户端上
PrintWriter outputToEachClient = new PrintWriter(
socket.getOutputStream());
outputToEachClient.println(sendMessage);
}
sendMessage = "";
}
}
} catch (Exception ex) {
ex.printStackTrace();
}

}
}

// Define the thread class for receive message
class ReceiveTask implements Runnable {
private MutiUser mu;

public ReceiveTask(MutiUser mu)
{
this.mu=mu;
}
public void run() {
try {
while (true) {
String receiveMessage = mu.input.readLine();
if (!receiveMessage.isEmpty()) {
jtaServer.append(receiveMessage + "\n");
sendMessage = receiveMessage;
}

}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

class MutiUser extends Thread {
private Socket server;
private BufferedReader input;

public MutiUser(Socket server) {
this.server = server;
}

public void run() {
try {
input = new BufferedReader(new InputStreamReader(
server.getInputStream()));
new Thread(new SendTask(this)).start();
new Thread(new ReceiveTask(this)).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
// TODO 自动生成方法存根
new Ex30_13Server();
}

}

wangdong20 2012-07-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
问题很多,主要是多线程数据同步的问题,建议你多看看这方面的书,学习使用java.util.concurrent包里的各种工具类。

尽量不要把代码都写在构造器里面,这是很不好的习惯。
[/Quote]
谢谢你的建议
wangdong20 2012-07-10
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
没看到你有什么问题要问
[/Quote]
client类里有时候发出的信息,Server接不到,其他的client就更接不到了
raistlic 2012-07-10
  • 打赏
  • 举报
回复
问题很多,主要是多线程数据同步的问题,建议你多看看这方面的书,学习使用java.util.concurrent包里的各种工具类。

尽量不要把代码都写在构造器里面,这是很不好的习惯。
zqfddqr 2012-07-10
  • 打赏
  • 举报
回复
没看到你有什么问题要问

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧