JAVA网络编程服务器多线程接受套接字,如何能使服务器的静态常量,与客户端的数据进行同步?

问题描述

JAVA网络编程服务器多线程接受套接字,如何能使服务器的静态常量,与客户端的数据进行同步?
服务器Server
客户端CLient
Server静态常量num
创建服务器,ServerSocket的端口号为8000,连接套接字。
每创建一个客户端,客户端就创建一个Socket,端口号为8000,与服务器进行连接,与此同时,客户端新建ServerSocket,端口号为3000+Server.num,连接套接字。
服务器与客户端连接后,服务器新建子线程Handler。
子线程Handler,新建ServerSocket,端口号为2000+Server.num,连接套接字。

每当有一个子线程创建,主线程都会加入一个子线程创建的对话界面(显示框,输入框,发送按钮)的选项卡
每当创建一个客户端,客户端都会创建一个对话界面

点击发送时,Hanlder会创建Socket,端口号为3000+Server.num。客户端会创建Socket,端口号为2000+Server.num

这是前提,现在我运行程序,但是当我每当创建一个客户端时,Server.num都不会改变,不知道怎么回事,急求大神解答,感激不尽!

以下是源代码,这里我讲Server.num抽离出去单独做成一个类NUM,每次Handler创建后,调用该类的增加函数numAdd():

服务器代码:

package NewPackage;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
private ServerSocket serverSocket;
private int PORT = 8000;
private Thread workThread;
private static MyServer server;
public static ArrayList solist = new ArrayList();
public static ArrayList ctlist = new ArrayList();

public Server() throws Exception {    serverSocket = new ServerSocket(PORT);}public void service() {    while (true) {        Socket socket = null;        try {            String s;            int num = NUM.num;            NUM.numadd();            socket = serverSocket.accept();            System.out.println(num + 2000);            workThread = new Thread(new Handler(num + 2000 MyServer.jp));            workThread.start();        } catch (Exception e) {            e.printStackTrace();        }    }}public static void main(String args[]) throws Exception {    server = new MyServer();    server.CreateGUI();    new Server().service();}

}

服务器的界面代码:
package NewPackage;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;

public class MyServer extends JFrame {

private static final long serialVersionUID = 1L;static JTextArea contentjta;static JScrollPane contentscroll;static JTextArea inputjta;static JScrollPane inputscroll;static JButton button;static JPanel jpanel;static JTabbedPane jp;MyServer() {    super(""Server Window"");}void CreateGUI() {    jp = new JTabbedPane();    this.add(jp BorderLayout.CENTER); // 将选项卡窗体添加到 主窗体上去    this.setSize(400 400);    this.setLocation(400 200);    this.setVisible(true);    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}

}

子线程Handler

package NewPackage;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;

public class Handler implements Runnable ActionListener {
private Socket socket;
private PrintWriter pw;
private int order;
private ServerSocket svs;
private MyClient client;
static JTextArea contentjta;
static JScrollPane contentscroll;
static JTextArea inputjta;
static JScrollPane inputscroll;
static JButton button;
static JPanel jpanel;
static JTabbedPane jp;
private BufferedReader br;

public Handler(int n JTabbedPane jp) {    try {        this.jp = jp;        // this.socket = socket;        // System.out.println(""handler"" + socket.getLocalPort());        order = n ;        // JOptionPane.showInputDialog(this order);        System.out.println(""Handler"" + order);        svs = new ServerSocket(order + 1000);        createTab();    } catch (Exception e) {        e.printStackTrace();    }}private PrintWriter getWriter(Socket socket) throws IOException {    OutputStream socketOut = socket.getOutputStream();    return new PrintWriter(socketOut true);}private BufferedReader getReader(Socket socket) throws IOException {    InputStream socketln = socket.getInputStream();    return new BufferedReader(new InputStreamReader(socketln));}void createTab() {    JPanel chat = new JPanel(new BorderLayout());    contentjta = new JTextArea(10 30);    contentjta.setTabSize(4);    contentjta.setFont(new Font(""楷体"" Font.BOLD 16));    contentjta.setEditable(false);    inputjta = new JTextArea(10 30);    inputjta.setTabSize(4);    inputjta.setFont(new Font(""楷体"" Font.BOLD 16));    inputjta.setEditable(true);    contentscroll = new JScrollPane(contentjta);    contentscroll            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);    contentscroll            .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);    inputscroll = new JScrollPane(inputjta);    inputscroll            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);    inputscroll            .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);    jpanel = new JPanel();    button = new JButton(""发送"");    button.addActionListener(this);    jpanel.setLayout(new GridLayout(1 1));    jpanel.add(button);    chat.add(contentscroll BorderLayout.NORTH);    chat.add(inputscroll BorderLayout.CENTER);    chat.add(jpanel BorderLayout.SOUTH);    jp.add(""aa"" chat);    jp.setFont(new Font(""宋体"" Font.BOLD 20));}public void run() {    try {        // 接受信息        while (true) {            Socket socket = svs.accept();            br = getReader(socket);            pw = getWriter(socket);            String msg = null;            String s = """";            while ((msg = br.readLine()) != null) {                s += msg;                if ((msg.equals(""bye"")))                    break;            }            contentjta.setText(s);        }    } catch (Exception e) {        e.printStackTrace();    }}@Overridepublic void actionPerformed(ActionEvent e) {    Object o = e.getSource();    if (o == button) {        try {            Socket so = new Socket(""localhost"" order);            OutputStream out = so.getOutputStream();            PrintStream pout = new PrintStream(out);            pout.print(inputjta.getText());            inputjta.setText("""");            out.flush();            out.close();        } catch (Exception ex) {            ex.printStackTrace();        }    }}

}

解决方案

字数限制,以下是其他内容

客户端代码:
package NewPackage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Client {
static int PORT = 2000;

public static void main(String[] args) {    int num = 1;    MyClient client = new MyClient(3000 + num);    client.CreateGUI();    try {        System.out.println(PORT + num);        ServerSocket serversocket = new ServerSocket(PORT + num);        NUM.numadd();        while (true) {            Socket socket = serversocket.accept();            BufferedReader br = new BufferedReader(new InputStreamReader(                    socket.getInputStream()));            String msg;            String s = """";            while (((msg = br.readLine()) != null)) {                s += msg;                if (msg.equals(""bye""))                    break;            }            System.out.println(s);            client.getContentjta().setText(s);        }    } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();    }}

}

客户端界面代码:
package NewPackage;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;

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

public class MyClient extends JFrame implements ActionListener {

private static final long serialVersionUID = 1L;static JTextArea contentjta;static JScrollPane contentscroll;static JTextArea inputjta;static JScrollPane inputscroll;static JButton button;static JPanel jpanel;private Socket socket;private int order;public static JTextArea getContentjta() {    return contentjta;}public MyClient(int n) {    super(""Client Window"");    order = n;}void CreateGUI() {    // System.out.println(""MyClient"" + order);    try {        socket = new Socket(""localhost"" 8000);        socket.close();    } catch (Exception e1) {        e1.printStackTrace();    }    JPanel chat = new JPanel(new BorderLayout());    contentjta = new JTextArea(10 30);    contentjta.setTabSize(4);    contentjta.setFont(new Font(""楷体"" Font.BOLD 16));    contentjta.setEditable(false);    inputjta = new JTextArea(10 30);    inputjta.setTabSize(4);    inputjta.setFont(new Font(""楷体"" Font.BOLD 16));    inputjta.setEditable(true);    contentscroll = new JScrollPane(contentjta);    contentscroll            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);    contentscroll            .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);    inputscroll = new JScrollPane(inputjta);    inputscroll            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);    inputscroll            .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);    jpanel = new JPanel();    button = new JButton(""发送"");    button.addActionListener(this);    jpanel.setLayout(new GridLayout(1 1));    jpanel.add(button);    chat.add(contentscroll BorderLayout.NORTH);    chat.add(inputscroll BorderLayout.CENTER);    chat.add(jpanel BorderLayout.SOUTH);    this.setSize(400 400);    this.setLocation(400 200);    this.setVisible(true);    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    this.add(chat);}@Overridepublic void actionPerformed(ActionEvent e) {    Object o = e.getSource();    if (o == button) {        try {            Socket so = new Socket(""localhost"" order);            OutputStream out = so.getOutputStream();            PrintStream pout = new PrintStream(out);            pout.print(inputjta.getText());            inputjta.setText("""");            out.flush();            out.close();        } catch (Exception ex) {            ex.printStackTrace();        }    }}

}

NUM类
package NewPackage;

public class NUM {
public static int num = 0;
static void numadd(){
num++;
}
}

时间: 2024-10-29 07:00:03

JAVA网络编程服务器多线程接受套接字,如何能使服务器的静态常量,与客户端的数据进行同步?的相关文章

《UNIX网络编程 卷1:套接字联网API(第3版)》——2.10 TCP端口号与并发服务器

2.10 TCP端口号与并发服务器 并发服务器中主服务器循环通过派生一个子进程来处理每个新的连接.如果一个子进程继续使用服务器众所周知的端口来服务一个长时间的请求,那将发生什么?让我们来看一个典型的序列.首先,在主机freebsd上启动服务器,该主机是多宿的,其IP地址为12.106.32.254和192.168.42.1.服务器在它的众所周知的端口(本例为21)上执行被动打开,从而开始等待客户的请求,如图2-11所示. 我们使用记号{:21, :}指出服务器的套接字对.服务器在任意本地接口(第

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.3 UDP回射服务器程序:main函数

8.3 UDP回射服务器程序:main函数 现在,我们用UDP重新编写第5章中简单的回射客户/服务器程序.我们的UDP客户程序和服务器程序依循图8-1中所示的函数调用流程.图8-2描述了它们所使用的函数,图8-3则给出了服务器程序的main函数. 创建UDP套接字,捆绑服务器的众所周知端口7~12 我们通过将socket函数的第二个参数指定为SOCK_DGRAM(IPv4协议中的数据报套接字)创建一个UDP套接字.正如TCP服务器程序的例子,用于bind的服务器IPv4地址被指定为INADDR_

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.15 使用select函数的TCP和UDP回射服务器程序

8.15 使用select函数的TCP和UDP回射服务器程序 现在,我们把第5章中的并发TCP回射服务器程序与本章中的迭代UDP回射服务器程序组合成单个使用select来复用TCP和UDP套接字的服务器程序.图8-24是该程序的前半部分. 创建监听TCP套接字14~22 创建一个监听TCP套接字并捆绑服务器的众所周知端口,设置SO_REUSEADDR套接字选项以防该端口上已有连接存在. 创建UDP套接字23~29 还创建一个UDP套接字并捆绑与TCP套接字相同的端口.这里无需在调用bind之前设

《UNIX网络编程 卷1:套接字联网API(第3版)》——1.8 BSD网络支持历史

1.8 BSD网络支持历史 套接字API起源于1983年发行的4.2BSD操作系统.图1-15展示了各种BSD发行版本的发展史,并注明了TCP/IP的主要发展历程.1990年面世的4.3BSD Reno发行版本随着OSI协议进入BSD内核而对套接字API做了少量的改动. 图1-15中从4.2BSD往下到4.4BSD的通路展示了源自Berkeley计算机系统研究组(Computer Systems Research Group,CSRG)的各个版本,它们要求获取者已拥有Unix的源代码许可权.然而

《UNIX网络编程 卷1:套接字联网API(第3版)》——1.5 一个简单的时间获取服务器程序

1.5 一个简单的时间获取服务器程序 我们可以编写一个简单的TCP时间获取服务器程序,它和1.2节中的客户程序一道工作.图1-9给出了这个服务器程序,它使用了上一节中讲过的包裹函数. 创建TCP套接字10 TCP套接字的创建与客户程序相同. 把服务器的众所周知端口捆绑到套接字11~15 通过填写一个网际套接字地址结构并调用bind函数,服务器的众所周知端口(对于时间获取服务是13)被捆绑到所创建的套接字.我们指定IP地址为INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.9 服务器进程未运行

8.9 服务器进程未运行 我们下一个要检查的情形是在不启动服务器的前提下启动客户.如果我们这么做后在客户上键入一行文本,那么什么也不发生.客户永远阻塞于它的recvfrom调用,等待一个永不出现的服务器应答.然而这是一个很好的例子,它要求我们更多地了解底层协议以理解网络应用进程将发生什么. 首先,我们在主机macosx上启动tcpdump,然后在同一个主机上启动客户,指定主机freebsd4为服务器主机.接着,我们键入一行文本,不过这行文本没有被回射. macosx % udpcli01 172

《UNIX网络编程 卷1:套接字联网API(第3版)》——2.6 TCP连接的建立和终止

2.6 TCP连接的建立和终止 为帮助大家理解connect.accept和close这3个函数并使用netstat程序调试TCP应用,我们必须了解TCP连接如何建立和终止,并掌握TCP的状态转换图. 2.6.1 三路握手建立一个TCP连接时会发生下述情形. (1)服务器必须准备好接受外来的连接.这通常通过调用socket.bind和listen这3个函数来完成,我们称之为被动打开(passive open). (2)客户通过调用connect发起主动打开(active open).这导致客户T

《UNIX网络编程 卷1:套接字联网API(第3版)》——第8章 基本UDP套接字编程 8.1概述

第8章 基本UDP套接字编程 8.1 概述 在使用TCP编写的应用程序和使用UDP编写的应用程序之间存在一些本质差异,其原因在于这两个传输层之间的差别:UDP是无连接不可靠的数据报协议,非常不同于TCP提供的面向连接的可靠字节流.然而相比TCP,有些场合确实更适合使用UDP,我们将在22.4节探讨这个设计选择.使用UDP编写的一些常见的应用程序有:DNS(域名系统).NFS(网络文件系统)和SNMP(简单网络管理协议). 图8-1给出了典型的UDP客户/服务器程序的函数调用.客户不与服务器建立连

《UNIX网络编程 卷1:套接字联网API(第3版)》——2.3 用户数据报协议(UDP)

2.3 用户数据报协议(UDP) UDP是一个简单的传输层协议,在RFC 768[Postel 1980]中有详细说明.应用进程往一个UDP套接字写入一个消息,该消息随后被封装(encapsulating)到一个UDP数据报,该UDP数据报进而又被封装到一个IP数据报,然后发送到目的地.UDP不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数据报只到达一次. 我们使用UDP进行网络编程所遇到的问题是它缺乏可靠性.如果一个数据报到达了其最终目的地,但是