就是一个简单的客户端发消息,服务器端接收的单向过程
服务器代码为
import java.net.*;
import java.io.*;public class SP {
private Socket s;
public DataInputStream dis;
public SP() throws Exception {
ServerSocket ss=new ServerSocket(6618);
//while(true) {
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
// }
}
public void CClose() throws Exception {
s.close();
dis.close();
}
}import javax.swing.*;
import java.awt.*;public class SUI extends JFrame {
private JTextArea JTA;
private Container container;
public SUI () {
super("进程通信");
try {
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
this.setLocation(234, 40);
this.setSize(400,240);
container.add(JTA);
this.setVisible(true);
while (true) {
SP C = new SP();
JTA.setText(C.dis.readUTF());
C.CClose();
}
}catch(Exception E){}
}
客户端代码为:import java.net.*;
import java.io.*;public class TCPClient {
private Socket s;
public DataOutputStream dos;
public TCPClient() throws Exception {
s=new Socket("127.0.0.1",6618);
OutputStream os = s.getOutputStream();
dos=new DataOutputStream(os);
}
public void CClose() throws Exception {
dos.flush();
dos.close();
s.close();
}}import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;public class CUI extends JFrame implements ActionListener {
private JTextArea JTA; private JButton JB1,JB2;
private JLabel JL;
private Container container;
public CUI () {
super("进程通信");
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
JL = new JLabel("客户端");
JB1 = new JButton("发送");
JB2 = new JButton("取消");
container.add(JL);
container.add(JTA);
container.add(JB1);
container.add(JB2);
JB1.addActionListener(this);
JB2.addActionListener(this);
this.setLocation(234, 40);
this.setSize(400,240);
this.setVisible(true); }
public void actionPerformed(ActionEvent e){
try {
TCPClient C = new TCPClient();
if(e.getSource()==JB1) {
if(JTA.getText()==null) {
JOptionPane.showMessageDialog(new JFrame(),
"发送内容不能为空!",
"进程通信",
JOptionPane.INFORMATION_MESSAGE
);
}
else {
C.dos.writeUTF(JTA.getText());
C.CClose();
}
}
else if(e.getSource()==JB2) {
JTA.setText(null);
}
}catch (Exception a){}
}
public static void main(String[] args) throws Exception{
new CUI();
}
}
代码有很多规范问题,现在这不是讨论的重点(初学)
我的问题是:
1.为什么每次运行程序只能发送一次消息,后面即使更改发送内容,服务器端仍没反应?
2.每次运行完后,关闭程序,然后再打开都需更换端口,不然的话程序没任何反应?
3.有人可能发现了我的服务器端没有循环监听(将死循环注释掉了),因为如果加上的话,程序同样没反应(一次都不能发送),哪出问题了?希望你能耐心看完,指点一二,不胜感激啊
服务器代码为
import java.net.*;
import java.io.*;public class SP {
private Socket s;
public DataInputStream dis;
public SP() throws Exception {
ServerSocket ss=new ServerSocket(6618);
//while(true) {
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
// }
}
public void CClose() throws Exception {
s.close();
dis.close();
}
}import javax.swing.*;
import java.awt.*;public class SUI extends JFrame {
private JTextArea JTA;
private Container container;
public SUI () {
super("进程通信");
try {
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
this.setLocation(234, 40);
this.setSize(400,240);
container.add(JTA);
this.setVisible(true);
while (true) {
SP C = new SP();
JTA.setText(C.dis.readUTF());
C.CClose();
}
}catch(Exception E){}
}
客户端代码为:import java.net.*;
import java.io.*;public class TCPClient {
private Socket s;
public DataOutputStream dos;
public TCPClient() throws Exception {
s=new Socket("127.0.0.1",6618);
OutputStream os = s.getOutputStream();
dos=new DataOutputStream(os);
}
public void CClose() throws Exception {
dos.flush();
dos.close();
s.close();
}}import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;public class CUI extends JFrame implements ActionListener {
private JTextArea JTA; private JButton JB1,JB2;
private JLabel JL;
private Container container;
public CUI () {
super("进程通信");
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
JL = new JLabel("客户端");
JB1 = new JButton("发送");
JB2 = new JButton("取消");
container.add(JL);
container.add(JTA);
container.add(JB1);
container.add(JB2);
JB1.addActionListener(this);
JB2.addActionListener(this);
this.setLocation(234, 40);
this.setSize(400,240);
this.setVisible(true); }
public void actionPerformed(ActionEvent e){
try {
TCPClient C = new TCPClient();
if(e.getSource()==JB1) {
if(JTA.getText()==null) {
JOptionPane.showMessageDialog(new JFrame(),
"发送内容不能为空!",
"进程通信",
JOptionPane.INFORMATION_MESSAGE
);
}
else {
C.dos.writeUTF(JTA.getText());
C.CClose();
}
}
else if(e.getSource()==JB2) {
JTA.setText(null);
}
}catch (Exception a){}
}
public static void main(String[] args) throws Exception{
new CUI();
}
}
代码有很多规范问题,现在这不是讨论的重点(初学)
我的问题是:
1.为什么每次运行程序只能发送一次消息,后面即使更改发送内容,服务器端仍没反应?
2.每次运行完后,关闭程序,然后再打开都需更换端口,不然的话程序没任何反应?
3.有人可能发现了我的服务器端没有循环监听(将死循环注释掉了),因为如果加上的话,程序同样没反应(一次都不能发送),哪出问题了?希望你能耐心看完,指点一二,不胜感激啊
你在SP中添加关闭ServerSocket的代码就行了\import java.net.*;
import java.io.*;public class SP
{
private Socket s;
public DataInputStream dis;
ServerSocket ss;
public SP() throws Exception
{
ss=new ServerSocket(6618);
//while(true) {
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
// }
}
public void CClose() throws Exception
{
s.close();
dis.close();
ss.close(); //在这里把ServerSocket也关了
}
}
第一个问题:
服务端ServerSocket创建你放在了public SP()构造方法里,而且是局部变量引用,所以当public SP()执行完毕,也就是服务器创建完毕之后,这个ServerSocket相对这个服务器对象来说已经消失了,因为你没有用一个全局变量引用它,相对内存来说,ServerSocket还没有消失,而且还没有关闭,这时候客户端再次发消息时,客户端会用一个新的socket去与ServerSocket建立连接,ServerSocket接收到连接还会分配出一个新的socket,楼主并未用新的socket读取信息,所以表象是只能发送读取一次
第二个问题:
肯定是端口被占用的问题,这一定是ServerSocket未关闭造成的,楼主仔细检查程序的推出代码是否正确,最简单的 System.exit(-1);
第三个问题:
while(true),死循环啊 ,除非内部代码抛异常,否则楼主的代码是不会退出循环的.
while(true)循环中,服务器一直在做接受连接的事情,所以我想楼主的情形是:客户端 发送 按钮点击无数次,都没反应,而且还没任何异常,解决方法是如果楼主不考虑多线程,就把循环去掉.总结;
楼主的主要问题:
1. 对整个交互过程,情景还不是太清楚.
2. 在代码实现上,代码结构混乱,主要还是上面原因造成的.
3. 对程序控制,比如说循环可能理解不够充分. 解决方案 你先自己想吧
1.JFame调用setVisible之后,还要调用setDefaultCloseOperation(3),不然的话,你点了窗体的关闭后,只是把窗体隐藏了,进程还没有退出,所以,再启动的话,就得换一个端口才行。
2.在SUI中的while中SP C = new SP();这个肯定不行,因为new SP的时候要创建ServerSocket。
应该在循环开始前创建ServerSocket,在循环中accept连接并读写数据。
SUI代码片段SP C = new SP();
while (true) {
C.listen();
JTA.setText(C.dis.readUTF());
C.CClose();
}SP代码片段public SP() throws Exception {
ss = new ServerSocket(6618);
}
public void listen() throws IOException{
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
}
服务器接收端,本就该用while(true)循环读取客户端的数据,
通用的端口接收数据的做法就是这么实现的。
不知道你为什么把while(true)循环给注释掉了?!这样的话只能读取一次!另外,退出循环的通用做法是,当客户端发送特殊信息,比如"quit","exit"的时候,
在while(true)循环内判断客户端发送的内容,再退出循环,关闭端口!有时间看看经典的JAVA教程。
是的,呵呵.但楼主的while(true)是用来不断接受客户端连接并分配与之对应的socket用的,这种情景下就需要给每个客户端分配一个线程独立去通信,
5楼的是正确的
while(true)循环是在某一个线程内不断接受某一个客户端的信息,
这并不矛盾。
搂主应该把服务器端代码分为两个模块
1.接收连接请求,建立连接,创建线程。
2.在这个启动的线程内循环读取客户端的信息。
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;public class CUI extends JFrame implements ActionListener
{
private JTextArea JTA;
private JButton JB1,JB2;
private JLabel JL;
private Container container;
public CUI () throws Exception
{
super("进程通信");
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
JL = new JLabel("客户端");
JB1 = new JButton("发送");
JB2 = new JButton("取消");
container.add(JL);
container.add(JTA);
container.add(JB1);
container.add(JB2);
JB1.addActionListener(this);
JB2.addActionListener(this);
this.setLocation(234, 40);
this.setSize(400,240);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} public void actionPerformed(ActionEvent e)
{
try
{
TCPClient C = new TCPClient();
if(e.getSource()==JB1)
{
if(JTA.getText()==null)
{
JOptionPane.showMessageDialog(new JFrame(),"发送内容不能为空!","进程通信",JOptionPane.INFORMATION_MESSAGE);
}
else
{
C.dos.writeUTF(JTA.getText());
C.CClose();
}
}
else if(e.getSource()==JB2)
{
JTA.setText(null);
}
}
catch (Exception a)
{
}
}
public static void main(String[] args) throws Exception
{
new CUI();
}
}
import javax.swing.*;
import java.awt.*;public class SUI extends JFrame
{
private JTextArea JTA;
private Container container;
public SUI ()
{
super("进程通信");
try
{
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
this.setLocation(234, 40);
this.setSize(400,240);
container.add(JTA);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true)
{
SP C = new SP();
JTA.setText(C.dis.readUTF());
C.CClose();
}
}
catch(Exception E)
{
}
}
public static void main(String[] args)
{
new SUI();
}
}
import java.net.*;
import java.io.*;public class SP
{
private Socket s;
public DataInputStream dis;
ServerSocket ss;
public SP() throws Exception
{
ss=new ServerSocket(6618);
//while(true) {
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
// }
}
public void CClose() throws Exception
{
s.close();
dis.close();
ss.close(); //在这里把ServerSocket也关了
}
}
import java.net.*;
import java.io.*;public class TCPClient
{
private Socket s;
public DataOutputStream dos; public TCPClient() throws Exception
{
s=new Socket("127.0.0.1",6618);
OutputStream os = s.getOutputStream();
dos=new DataOutputStream(os);
}
public void CClose() throws Exception
{
dos.flush();
dos.close();
s.close();
}
}运行时先运行SUI,再运行CUI,关闭时同时关闭。这样应该不会有问题了吧
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;public class CUI extends JFrame implements ActionListener
{
private JTextArea JTA;
private JButton JB1,JB2;
private JLabel JL;
private Container container;
public CUI () throws Exception
{
super("进程通信");
this.setLayout(new FlowLayout());
container = this.getContentPane();
JTA = new JTextArea();
JTA.setRows(6);
JTA.setColumns(30);
JL = new JLabel("客户端");
JB1 = new JButton("发送");
JB2 = new JButton("取消");
container.add(JL);
container.add(JTA);
container.add(JB1);
container.add(JB2);
JB1.addActionListener(this);
JB2.addActionListener(this);
this.setLocation(234, 40);
this.setSize(400,240);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} public void actionPerformed(ActionEvent e)
{
try
{
if(e.getSource()==JB1)
{
TCPClient C = new TCPClient();
if(JTA.getText()==null)
{
JOptionPane.showMessageDialog(new JFrame(),"发送内容不能为空!","进程通信",JOptionPane.INFORMATION_MESSAGE);
}
else
{
C.dos.writeUTF(JTA.getText());
C.CClose();
}
}
else if(e.getSource()==JB2)
{
JTA.setText(null);
}
}
catch (Exception a)
{
}
}
public static void main(String[] args) throws Exception
{
new CUI();
}
}