问个图形化echo程序的问题,搞不懂啊

做《java开发实战经典》后面的练习题:将Echo程序进行扩充,通过图形界面编写服务器和客户端,实现通过按钮控制服务器的启动与关闭,并使用界面发送和接收服务器的返回信息。

我现在做到的界面是这样的:

但是程序里面开启服务器端的语句只要加上,那个图形界面就不会出现,把它注释掉就可以出现了,搞不明白是哪里的问题了,eclipse里面也没任何错误提示什么的,麻烦各位给看看,初学,程序很烂,见笑见笑。


package xiti19;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import java.net.*;
import java.io.*;
class EchoServer{
private static ServerSocket svrSkt=null;
private Socket cltSkt=null;
private BufferedReader input=null; //输入流,来自客户端
private PrintStream output=null; //输出流,指向客户端
private JTextArea text = null;
public EchoServer(JTextArea serverText,int port){
text = serverText;
text.append("服务器代理正在监听,端口:"+port+"\n");
try{
svrSkt=new ServerSocket(port); //开始监听
}catch(IOException e){
text.append("监听端口"+port+"失败\n");}
try{
cltSkt=svrSkt.accept(); //接收连接请求
}catch(IOException e){
text.append("连接失败\n");}
try{
input=new BufferedReader(new InputStreamReader(cltSkt.getInputStream())); //获得输入流
output=new PrintStream(cltSkt.getOutputStream()); //获得输出流
}catch(IOException e){}
text.append("欢迎......\n");
}

public String getRequest(){
String frmClt=null;
try{
frmClt=input.readLine();
}catch(Exception e){
System.out.println("无法读取端口.....");
System.exit(0);
}
return frmClt;
}
public void sendResponse(String response){
try{
output.println("ECHO:"+response);
}catch(Exception e){
System.out.println("写端口失败......");
System.exit(0);
}
}
public static void CloseServer() throws Exception{
svrSkt.close();
}
}
class EchoClient{
private PrintStream ops; //输出流(指向服务器)
private BufferedReader ips;//输入流(来自服务器)
private JTextArea text = null;

public EchoClient(JTextArea clientText,String serverName,int port){
text = clientText;
try{
Socket clientSocket=new Socket(serverName,port); //根据服务器名和端口号建立Socket
ops=new PrintStream(clientSocket.getOutputStream());//获得Socket的输出流
ips=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//获得Socket的输入流
}catch(Exception e){
text.append("无法连接服务器!\n");
}
}
public void sendRequest(String request){
ops.println(request); //向Socket的输出流写入字符串
}
public String getResponse(){
String str=new String();
try{
str=ips.readLine(); //从Socket的输入流读入字符串
}catch(IOException e){} //必须捕获错误
return str;
}
}
public class XiTi19_1 {
public static void main(String args[]){
JFrame frame = new JFrame("ECHO图形界面");
final JButton startBut = new JButton("启动服务器");
final JButton stopBut = new JButton("停止服务器");
final JTextArea serverText = new JTextArea("服务器显示界面\n");
final JTextArea clientText = new JTextArea("客户端显示界面\n");
final JTextField inputField = new JTextField("这里输入信息",20);
final JButton sendBut = new JButton("发送");
//final EchoServer sa = new EchoServer(serverText,8888);
final EchoClient ca = new EchoClient(clientText,"localhost",8888);
JScrollPane scrServer = new JScrollPane(serverText,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
JScrollPane scrClient = new JScrollPane(clientText,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
GridBagLayout gr = new GridBagLayout();
GridBagConstraints gc = new GridBagConstraints(); //创建一个名为gc的约束对象
frame.setLayout(gr); //将容器的布局设为GridBagLayout
gc.weighty =4;
gc.fill = GridBagConstraints.BOTH;
gc.gridwidth = GridBagConstraints.REMAINDER;//设置gridwidth参数的值为REMAINDER这样在后面使用该约束的组件将是该行的最后一个组件。
gr.setConstraints(scrServer, gc);
GridBagConstraints gc3 = new GridBagConstraints();
gc3.weighty =1;
gc3.weightx =3;
gr.setConstraints(startBut, gc3);
gc3.gridwidth = GridBagConstraints.REMAINDER;
gr.setConstraints(stopBut, gc3);
GridBagConstraints gc1 = new GridBagConstraints();
gc1.weightx = 8;
gc1.weighty = 1;
gr.setConstraints(inputField, gc1);
gc1.gridwidth = GridBagConstraints.REMAINDER;
gc1.weightx = 2;
gr.setConstraints(sendBut, gc1);
GridBagConstraints gc2 = new GridBagConstraints();
gc2.weighty = 4;
gc2.fill = GridBagConstraints.BOTH;
gc2.gridwidth = GridBagConstraints.REMAINDER;
gr.setConstraints(scrClient, gc2);

startBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
if(arg0.getSource()==startBut){
try {
while(true){
sa.sendResponse(sa.getRequest());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
stopBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
if(arg0.getSource()==stopBut){
try {
EchoServer.CloseServer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
sendBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
if(arg0.getSource()==sendBut){
try {
ca.sendRequest(inputField.getText()); //发送文本框中的文本
clientText.append("\n"+ca.getResponse()); //接收服务器回应并写入文本域
} catch (Exception e) {
e.printStackTrace();
}
}
}
});

frame.add(scrServer);
frame.add(startBut);
frame.add(stopBut);
frame.add(inputField);
frame.add(sendBut);
frame.add(scrClient);
frame.setSize(400,400);
frame.setLocation(300,200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}
}


//final EchoServer sa = new EchoServer(serverText,8888);就这一句,如果不注释就不会出现图形界面,注释了可以出现,但服务器相当于没有启动,没法往下测试了,看了半天也不知道那有问题了,请大家帮忙,谢谢!
...全文
371 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
搞定了,把服务器和客户端的代码分别弄两个文件,都用线程启动,在主文件里面放两个按钮分别来启动他们,还是那个server.accept()的问题,不用线程的话,到那句就阻塞了,没法继续了。
  • 打赏
  • 举报
回复
我有单独写了个主程序,想把客户端的也用线程来启动,然后在主程序里面就放两个按钮,一个是启动服务器,一个是启动客户端去打开另外一个frame,怎么一直提示我没有定义start()方法?

package xiti19;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

class Client{
	private PrintStream ops; //输出流(指向服务器)
	private BufferedReader ips;//输入流(来自服务器)
	private JTextArea text = null;
	
	public Client(JTextArea clientText,String serverName,int port){
		text = clientText;
		try{ 
			Socket clientSocket=new Socket(serverName,port); //根据服务器名和端口号建立Socket
			ops=new PrintStream(clientSocket.getOutputStream());//获得Socket的输出流
			ips=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//获得Socket的输入流
		}catch(Exception e){
			text.append("无法连接服务器!\n");
		}
	}
	public void sendRequest(String request){
		ops.println(request); //向Socket的输出流写入字符串
	}
	public String getResponse(){
		String str=new String();
		try{
			str=ips.readLine(); //从Socket的输入流读入字符串
		}catch(IOException e){} //必须捕获错误
		return str;
	}
}
public class ClientThread implements Runnable{
	
	public void run(){
		JFrame frame1 = new JFrame("ECHO客户端界面");
		final JTextArea clientText = new JTextArea("客户端显示界面\n");
		final JTextField inputField = new JTextField("这里输入信息",20);
		final JButton sendBut = new JButton("发送");
		JScrollPane scrClient = new JScrollPane(clientText,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		GridBagLayout gr = new GridBagLayout();
        frame1.setLayout(gr);    //将容器的布局设为GridBagLayout
        GridBagConstraints gc1 = new GridBagConstraints();
        gc1.weightx = 8;
        gc1.weighty = 1;
        gr.setConstraints(inputField, gc1);
        gc1.gridwidth = GridBagConstraints.REMAINDER;
        gc1.weightx = 2;
        gr.setConstraints(sendBut, gc1);
        GridBagConstraints gc2 = new GridBagConstraints();
        gc2.weighty = 4;
        gc2.fill = GridBagConstraints.BOTH;
        gc2.gridwidth = GridBagConstraints.REMAINDER;
        gr.setConstraints(scrClient, gc2);
        final Client ca = new Client(clientText,"localhost",8888);
        sendBut.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0){
				if(arg0.getSource()==sendBut){
					try {
						ca.sendRequest(inputField.getText()); //发送文本框中的文本
						clientText.append(ca.getResponse()); //接收服务器回应并写入文本域
						clientText.append("\n");
						clientText.setSelectionStart(clientText.getText().length());
						clientText.paintImmediately(clientText.getBounds());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
		
		frame1.add(inputField);
		frame1.add(sendBut);
		frame1.add(scrClient);
		frame1.setSize(400,400);		
		frame1.setLocation(300,200);
		frame1.setVisible(true);
		frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
这样写不对吗?
  • 打赏
  • 举报
回复
我现在把服务器端和客户端分开了,服务器端用线程启动,客户端里面加个按钮来启动服务器,可是点了按钮以后还是阻塞了,其他的按钮都点不了了,包括关闭那个frame都不行了,很是奇怪啊。 服务器的代码是这样的:

package xiti19;

import java.net.* ;
import java.io.* ;
public class EchoThread implements Runnable{
	private Socket client = null ;
	public EchoThread(Socket client){
		this.client = client ;
	}
	public void run(){
		BufferedReader buf = null ;	// 接收输入流
		PrintStream out = null ;		// 打印流输出最方便
		try{
			out = new PrintStream(client.getOutputStream()) ;
			// 准备接收客户端的输入信息
			buf = new BufferedReader(new InputStreamReader(client.getInputStream())) ;
			boolean flag = true ;	// 标志位,表示可以一直接收并回应信息
			while(flag){
				String str = buf.readLine() ;		// 接收客户端发送的内容
				if(str==null||"".equals(str)){	// 表示没有内容
					flag = false ;	// 退出循环
				}else{
					if("bye".equals(str)){	// 如果输入的内容为bye表示结束
						flag = false ;
					}else{
						out.println("ECHO : " + str) ;	// 回应信息
					}
				}
			}
			client.close() ;
		}catch(Exception e){}
		
	}
}
客户端的现在写成这样了,还没搞好,但启动服务器还没通过,后面的就没法再改了:

package xiti19;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import java.net.*;
import java.io.*;

class EchoClient1{
	private PrintStream ops; //输出流(指向服务器)
	private BufferedReader ips;//输入流(来自服务器)
	private JTextArea text = null;
	
	public EchoClient1(JTextArea clientText,String serverName,int port){
		text = clientText;
		try{ 
			Socket clientSocket=new Socket(serverName,port); //根据服务器名和端口号建立Socket
			ops=new PrintStream(clientSocket.getOutputStream());//获得Socket的输出流
			ips=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//获得Socket的输入流
		}catch(Exception e){
			text.append("无法连接服务器!\n");
		}
	}
	public void sendRequest(String request){
		ops.println(request); //向Socket的输出流写入字符串
	}
	public String getResponse(){
		String str=new String();
		try{
			str=ips.readLine(); //从Socket的输入流读入字符串
		}catch(IOException e){} //必须捕获错误
		return str;
	}
}
public class EchoClient {
	public static void main(String args[]){
		JFrame frame = new JFrame("ECHO图形界面");
		final JTextArea clientText = new JTextArea("客户端显示界面\n");
		final JTextField inputField = new JTextField("这里输入信息",20);
		final JButton sendBut = new JButton("发送");
		JScrollPane scrClient = new JScrollPane(clientText,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		GridBagLayout gr = new GridBagLayout();
        frame.setLayout(gr);    //将容器的布局设为GridBagLayout
        GridBagConstraints gc1 = new GridBagConstraints();
        gc1.weightx = 8;
        gc1.weighty = 1;
        gr.setConstraints(inputField, gc1);
        gc1.gridwidth = GridBagConstraints.REMAINDER;
        gc1.weightx = 2;
        gr.setConstraints(sendBut, gc1);
        GridBagConstraints gc2 = new GridBagConstraints();
        gc2.weighty = 4;
        gc2.fill = GridBagConstraints.BOTH;
        gc2.gridwidth = GridBagConstraints.REMAINDER;
        gr.setConstraints(scrClient, gc2);
        final EchoClient1 ca = new EchoClient1(clientText,"localhost",8888);
        sendBut.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0){
				if(arg0.getSource()==sendBut){
					try {
						ca.sendRequest(inputField.getText()); //发送文本框中的文本
						clientText.append(ca.getResponse()); //接收服务器回应并写入文本域
						clientText.append("\n");
						clientText.setSelectionStart(clientText.getText().length());
						clientText.paintImmediately(clientText.getBounds());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
		
		frame.add(inputField);
		frame.add(sendBut);
		frame.add(scrClient);
		frame.setSize(400,400);		
		frame.setLocation(300,200);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
	}
}
teemai 2013-10-22
  • 打赏
  • 举报
回复
可以把这个accpet单独抽出来写一个方法,不要在构造方法里调用
teemai 2013-10-22
  • 打赏
  • 举报
回复
cltSkt=svrSkt.accept(); //接收连接请求 这里是阻塞式 看看API解释: public Socket accept() throws IOException Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made. A new Socket s is created and, if there is a security manager, the security manager's checkAccept method is called with s.getInetAddress().getHostAddress() and s.getPort() as its arguments to ensure the operation is allowed. This could result in a SecurityException. Returns: the new Socket Throws: IOException - if an I/O error occurs when waiting for a connection. SecurityException - if a security manager exists and its checkAccept method doesn't allow the operation. SocketTimeoutException - if a timeout was previously set with setSoTimeout and the timeout has been reached. IllegalBlockingModeException - if this socket has an associated channel, the channel is in non-blocking mode, and there is no connection ready to be accepted See Also: SecurityManager.checkAccept(java.lang.String, int)
zhuweisyyc 2013-10-22
  • 打赏
  • 举报
回复
cltSkt=svrSkt.accept(); 好像就一直等待了,下面的代码就走不下去了
zhuweisyyc 2013-10-22
  • 打赏
  • 举报
回复
我猜是跟线程有关,能不能把界面的线程和启动server的线程独立下。
小行星0906 2013-10-22
  • 打赏
  • 举报
回复
引用 楼主 zhiqiu 的回复:
楼主debug下看会发现在new EchoServer()时候抛异常了,我看你里面捕获异常了,我就尝试了下打印到控制台看看。

public EchoServer(JTextArea serverText, int port)
	{
		text = serverText;
		text.append("服务器代理正在监听,端口:" + port + "\n");
		
		try
		{
			svrSkt = new ServerSocket(port); // 开始监听
		}
		catch (IOException e)
		{
			text.append("监听端口" + port + "失败\n");
			System.out.println("开始监听");
		}
		
		try
		{
			cltSkt = svrSkt.accept(); // 接收连接请求
		}
		catch (IOException e)
		{
			text.append("连接失败\n");
			System.out.println("开始监听2");
		}
		
		try
		{
			input = new BufferedReader(new InputStreamReader(cltSkt.getInputStream())); // 获得输入流
			output = new PrintStream(cltSkt.getOutputStream()); // 获得输出流
		}
		catch (IOException e)
		{
			System.out.println("开始监听3");
		}
		
		text.append("欢迎......\n");
	}
结果得到是: Exception in thread "main" 开始监听 java.lang.NullPointerException at com.nyohh.test.xiti19.EchoServer.<init>(EchoServer.java:37) 然后我得的结论就是main方法里面运行到new EchoServer(serverText,8888);出错,具体在 EchoServer()的输出“开始监听”出错的,所以就是:

try
		{
			svrSkt = new ServerSocket(port); // 开始监听
		}
		catch (IOException e)
		{
			text.append("监听端口" + port + "失败\n");
			System.out.println("开始监听");
		}
怎么解决,说实话楼主,重构下你这个代码,思路再清晰些 把你客户端和服务端先分离开,应该有两个main入口,分别启动客户端和服务端 界面和业务分离下,你的成品界面我做不来,但是程序的业务不复杂。 然后从服务端的功能开始一点点做

62,630

社区成员

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

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