我正在尝试编写多个客户端服务器聊天。一切都应该在同一台计算机上运行,每个客户端都在不同的shell终端控制台中。我在这方面阅读了几个线程,人们说,我应该在服务器上为每个连接的客户端运行新线程。这就是我所做的。但是,服务器在其控制台上打印来自每个客户端的消息,但客户只能看到他们写的消息,而不是每次聊天时提交的消息。我该怎么做才能解决它?
这是代码: 服务器:
//package javauj.serwer;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Server {
private static final int PORT_NUM = 5051;
private static ServerSocket serS;
private static Socket s;
public static void main(String[] args) throws IOException{
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
Calendar cal = Calendar.getInstance();
System.out.println(df.format(cal.getTime())+" Server waiting on port "+PORT_NUM);
try {
serS = new ServerSocket(PORT_NUM);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true){
try {
s = serS.accept();
System.out.println("New user connected");
ServerThread st=new ServerThread(s);
st.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
服务器线程:
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Scanner;
public class ServerThread extends Thread {
Socket socket=null;
private Scanner sc;
private PrintStream ps;
public ServerThread(Socket s) {
this.socket=s;
}
public void run(){
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
Calendar cal = Calendar.getInstance();
String response;
while(true){
try {
sc = new Scanner(socket.getInputStream());
ps = new PrintStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if((response=sc.nextLine())!=null){
System.out.println(df.format(cal.getTime())+" Napisal "+response);
ps.println(df.format(cal.getTime())+" Napisal :"+response);
}
}
}
}
和客户
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
static Scanner sc;
static Scanner sc2;
static Socket s;
static String response;
public static void main(String[]args) throws UnknownHostException, IOException{
String send;
sc=new Scanner(System.in); //client send scanner
s = new Socket("127.0.0.1", 5051);
sc2 = new Scanner(s.getInputStream()); //client response scanner
PrintStream ps = new PrintStream(s.getOutputStream());
while(true){
System.out.println(">");
send = sc.nextLine();
ps.println(send);
// I tried run new thread for responses
//Thread thread = new Thread(new Runnable(){
//public void run(){
//while(true){
response=sc2.nextLine();
System.out.println(response);
// }
//}
//});
}
}
}
答案 0 :(得分:2)
客户端需要两个线程:
第一个线程(来自服务器的阅读器)只是读取传入的消息并将其打印到控制台
第二个线程(服务器的编写者)接受用户输入并将其发送到服务器。
实际上在你的代码中,客户端上只有一个线程(主线程)。
答案 1 :(得分:0)
您必须在ServerThread实例和服务器之间实现通信(例如通过接口)。必须通知服务器有关ServerThread获取的消息,然后将此消息转换为其他(先前建立的)套接字(必须跟踪)。
您的客户端有两个扫描程序,但其中一个实际上阻止了另一个在nextLine()调用上。因此,您必须在单独的线程中运行其中一个扫描程序。
以下代码适用于我,但必须考虑线程安全性:
public interface MessageListener {
void acceptMessage(String message);
}
public class Server {
private static final int PORT_NUM = 5051;
private static ServerSocket serS;
private static List<PrintStream> sockets = new ArrayList<PrintStream>();
public static void main(String[] args) throws IOException{
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
Calendar cal = Calendar.getInstance();
System.out.println(df.format(cal.getTime())+" Server waiting on port "+PORT_NUM);
try {
serS = new ServerSocket(PORT_NUM);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MessageListener listener = new MessageListener() {
@Override
public void acceptMessage(String message) {
Iterator<PrintStream> it = sockets.iterator();
while (it.hasNext()) {
PrintStream ps = it.next();
ps.println("Have got message: " + message);
}
}
};
while(true){
try {
Socket s = serS.accept();
sockets.add(new PrintStream(s.getOutputStream()));
System.out.println("New user connected");
ServerThread st=new ServerThread(s, listener);
st.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class ServerThread extends Thread {
Socket socket=null;
private Scanner sc;
//private PrintStream ps;
private final MessageListener listener;
public ServerThread(Socket s, MessageListener listener) {
this.socket=s;
this.listener = listener;
}
public void run(){
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
Calendar cal = Calendar.getInstance();
String response;
while(true){
try {
sc = new Scanner(socket.getInputStream());
//ps = new PrintStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if((response=sc.nextLine())!=null){
System.out.println(df.format(cal.getTime())+" Napisal "+response);
//ps.println(df.format(cal.getTime())+" Napisal :"+response);
listener.acceptMessage(response);
}
}
}
}
public class Client {
static Scanner sc;
static Scanner sc2;
static Socket s;
static String response;
public static void main(String[]args) throws UnknownHostException, IOException{
String send;
sc=new Scanner(System.in); //client send scanner
s = new Socket("127.0.0.1", 5051);
ResponseListener l = new ResponseListener(new Scanner(s.getInputStream()));
Thread t = new Thread(l);
t.start();
PrintStream ps = new PrintStream(s.getOutputStream());
while(true){
System.out.println(">");
send = sc.nextLine();
ps.println(send);
}
}
static class ResponseListener implements Runnable {
private final Scanner scanner;
ResponseListener(Scanner scanner) {
this.scanner = scanner;
}
@Override
public void run() {
while (true) {
response = scanner.nextLine();
System.out.println(response);
}
}
}
}