尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码。代码如下:

 package project1;

 import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*; public class Server {
private JFrame serverFrame;
private JLabel portLabel;
private JLabel sayLabel;
private JLabel nicknameLabel;
private JTextField portText;
private JTextField sayText;
private JTextField nicknameText;
private JButton startButton;
private JButton sayButton;
private JButton nicknameButton;
private JPanel jPanelNorth;
private JPanel jPanelSouth0;
private JPanel jPanelSouth1;
private JPanel jPanelSouth2;
private JScrollPane scroller;
private JTextArea serverTextArea;
private ArrayList<PrintWriter> clientOutputStreams;
private String nickname; public static void main(String[] args) {
Server aServer = new Server();
aServer.startUp();
} // 初始化组件
public Server() {
nickname = "服务器"; serverFrame = new JFrame();
jPanelNorth = new JPanel();
portLabel = new JLabel("端口", JLabel.LEFT);
portText = new JTextField(30);
startButton = new JButton("开始");
serverTextArea = new JTextArea();
scroller = new JScrollPane(serverTextArea);
nicknameLabel = new JLabel("昵称", JLabel.LEFT);
nicknameText = new JTextField(nickname, 30);
nicknameButton = new JButton("确认");
jPanelSouth0 = new JPanel();
jPanelSouth1 = new JPanel();
jPanelSouth2 = new JPanel();
sayLabel = new JLabel("消息", JLabel.LEFT);
sayText = new JTextField(30);
sayButton = new JButton("确认");
} // 构建GUI
private void buildGUI() {
// 窗口的设置
serverFrame.setTitle("服务器");
serverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
serverFrame.setSize(550, 550); // 北区的组件
jPanelNorth.add(portLabel);
jPanelNorth.add(portText);
jPanelNorth.add(startButton);
serverFrame.getContentPane().add(BorderLayout.NORTH, jPanelNorth); // 中间的组件
serverTextArea.setFocusable(false);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
serverFrame.getContentPane().add(BorderLayout.CENTER, scroller); // 南区的组件
jPanelSouth1.add(nicknameLabel);
jPanelSouth1.add(nicknameText);
jPanelSouth1.add(nicknameButton);
jPanelSouth2.add(sayLabel);
jPanelSouth2.add(sayText);
jPanelSouth2.add(sayButton);
jPanelSouth0.setLayout(new BoxLayout(jPanelSouth0, BoxLayout.Y_AXIS));
jPanelSouth0.add(jPanelSouth1);
jPanelSouth0.add(jPanelSouth2);
serverFrame.getContentPane().add(BorderLayout.SOUTH, jPanelSouth0); // 设置窗口可见
serverFrame.setVisible(true);
} // 服务器运行
public void startUp() {
buildGUI(); // 监听Start按钮,建立端口
ActionListener startListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clientOutputStreams = new ArrayList<PrintWriter>();
String aPort = portText.getText(); if (aPort.equals("")) {
JOptionPane.showMessageDialog(serverFrame, "请输入正确的端口号!");
} else {
try {
// 等待客户端连接的线程
Runnable serverRunnable = new Runnable() {
@Override
public void run() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(Integer.parseInt(aPort));
serverTextArea.append("正在等待客户端连接...\n");
while (true) {
Socket clientSocket = serverSocket.accept();
serverTextArea.append("客户端已连接...\n"); PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
clientOutputStreams.add(writer); Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
}
} catch (NumberFormatException | IOException e) {
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverRunnable);
serverThread.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
};
startButton.addActionListener(startListener);
portText.addActionListener(startListener); // 监听nickname,设置昵称
ActionListener nicknameListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String aText = nicknameText.getText();
if (!aText.equals("")) {
nickname = aText;
}
}
};
nicknameButton.addActionListener(nicknameListener);
nicknameText.addActionListener(nicknameListener);
nicknameText.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
} @Override
public void focusLost(FocusEvent e) {
String aText = nicknameText.getText();
if (!aText.equals("")) {
nickname = aText;
}
}
}); // 监听Say按钮,发送消息
ActionListener SayListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String aText = sayText.getText();
if (!aText.equals("")) {
aText = nickname + ":" + aText;
sendToEveryClient(aText);
serverTextArea.append(aText + "\n");
sayText.setText("");
} else {
JOptionPane.showMessageDialog(serverFrame, "内容不能为空!");
}
}
};
sayButton.addActionListener(SayListener);
sayText.addActionListener(SayListener);
} // 多客户端的线程
public class ClientHandler implements Runnable {
BufferedReader bReader;
Socket aSocket; public ClientHandler(Socket clientSocket) {
try {
aSocket = clientSocket;
InputStreamReader isReader = new InputStreamReader(aSocket.getInputStream());
bReader = new BufferedReader(isReader);
} catch (Exception ex) {
ex.printStackTrace();
}
} @Override
public void run() {
String message;
try {
while ((message = bReader.readLine()) != null) {
sendToEveryClient(message);
serverTextArea.append(message + "\n");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
} // 发送消息给所有客户端的方法
private void sendToEveryClient(String message) {
Iterator<PrintWriter> it = clientOutputStreams.iterator();
while (it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
} }
 package project1;

 import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*; import javax.swing.*; public class Client {
private JFrame clientFrame;
private JLabel IPLabel;
private JLabel PortLabel;
private JLabel sayLabel;
private JLabel nicknameLabel;
private JTextField IPText;
private JTextField PortText;
private JTextField nicknameText;
private JTextField sayText;
private JButton connectButton;
private JButton nicknameButton;
private JButton sayButton;
private JPanel jPanelNorth;
private JPanel jPanelSouth0;
private JPanel jPanelSouth1;
private JPanel jPanelSouth2;
private JTextArea clientTextArea;
private JScrollPane scroller;
private BufferedReader reader;
private PrintWriter writer;
private String nickname; public static void main(String args[]) {
Client aClient = new Client();
aClient.startUp();
} // 初始化组件
public Client() {
nickname = "客户端"; clientFrame = new JFrame();
jPanelNorth = new JPanel();
IPLabel = new JLabel("服务器IP", JLabel.LEFT);
IPText = new JTextField(10);
PortLabel = new JLabel("服务器端口", JLabel.LEFT);
PortText = new JTextField(10);
connectButton = new JButton("连接");
clientTextArea = new JTextArea();
scroller = new JScrollPane(clientTextArea);
jPanelSouth0 = new JPanel();
jPanelSouth1 = new JPanel();
jPanelSouth2 = new JPanel();
nicknameLabel = new JLabel("昵称", JLabel.LEFT);
nicknameText = new JTextField(nickname, 30);
nicknameButton = new JButton("确认");
sayLabel = new JLabel("消息", JLabel.LEFT);
sayText = new JTextField(30);
sayButton = new JButton("确认");
} // 构建GUI
private void buildGUI() {
// 窗口的设置
clientFrame.setTitle("客户端");
clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
clientFrame.setSize(550, 550); // 北区的组件
jPanelNorth.add(IPLabel);
jPanelNorth.add(IPText);
jPanelNorth.add(PortLabel);
jPanelNorth.add(PortText);
jPanelNorth.add(connectButton);
clientFrame.getContentPane().add(BorderLayout.NORTH, jPanelNorth); // 中间的组件
clientTextArea.setFocusable(false);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
clientFrame.getContentPane().add(BorderLayout.CENTER, scroller); // 南区的组件
jPanelSouth1.add(nicknameLabel);
jPanelSouth1.add(nicknameText);
jPanelSouth1.add(nicknameButton);
jPanelSouth2.add(sayLabel);
jPanelSouth2.add(sayText);
jPanelSouth2.add(sayButton);
jPanelSouth0.setLayout(new BoxLayout(jPanelSouth0, BoxLayout.Y_AXIS));
jPanelSouth0.add(jPanelSouth1);
jPanelSouth0.add(jPanelSouth2);
clientFrame.getContentPane().add(BorderLayout.SOUTH, jPanelSouth0); // 设置窗口可见
clientFrame.setVisible(true);
} // 客户端运行
public void startUp() {
buildGUI(); // 接收服务器消息的线程
Runnable incomingReader = new Runnable() {
@Override
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
clientTextArea.append(message + "\n");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}; // 监听Connect按钮,实现服务器的连接
connectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String aServerIP = IPText.getText();
String aServerPort = PortText.getText(); if (aServerIP.equals("") || aServerPort.equals("")) {
JOptionPane.showMessageDialog(clientFrame, "请输入 完整的 IP和端口!");
} else {
try {
@SuppressWarnings("resource")
Socket clientSocket = new Socket(aServerIP, Integer.parseInt(aServerPort));
InputStreamReader streamReader = new InputStreamReader(clientSocket.getInputStream());
reader = new BufferedReader(streamReader);
writer = new PrintWriter(clientSocket.getOutputStream()); clientTextArea.append("服务器已连接...\n"); Thread readerThread = new Thread(incomingReader);
readerThread.start();
} catch (Exception ex) {
JOptionPane.showMessageDialog(clientFrame, "连接不上服务器!\n请确认 IP 和 端口 输入正确。");
}
}
}
}); // 监听nickname,设置昵称
ActionListener nicknameListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String aText = nicknameText.getText();
if (!aText.equals("")) {
nickname = aText;
}
}
};
nicknameButton.addActionListener(nicknameListener);
nicknameText.addActionListener(nicknameListener);
nicknameText.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
} @Override
public void focusLost(FocusEvent e) {
String aText = nicknameText.getText();
if (!aText.equals("")) {
nickname = aText;
}
}
}); // 发送消息到服务器
ActionListener SayListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String aText = sayText.getText();
if (aText.equals("")) {
JOptionPane.showMessageDialog(clientFrame, "内容不能为空!");
} else {
try {
writer.println(nickname + ":" + aText);
writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
sayText.setText("");
}
}
};
sayButton.addActionListener(SayListener);
sayText.addActionListener(SayListener); } }

运行结果如下:

下面主要探讨一下Java中的socket与Linux中的socket API之间的联系。主要思路当然是查看一下Java中的serversocket和socket的源码,这样更清楚地明白底层Java调用栈。

首先要明白的一点是,Java实现的socket与Linux提供的socket是否一定是有关呢?答案是否定的!关键要看Java虚拟机是怎么实现的。

如果Java虚拟机是在Linux系统之上的,并且使用了系统调用,那显然两者之间有关系。并且JVM最后一定是调用了LinuxSocket。

但是如果是在一个裸机上实现的虚拟机或者其他非Linux系统上实现Java虚拟机,那显然二者之间没有一毛钱关系,最终只是有相同的接口名称而已。

所以最终还是要看JVM是怎么实现的。JVM屏蔽了底层不同的机器特性,向上提供了一个统一的虚拟机接口,所以还是JVM牛逼。

Java实现网络聊天中使用的socket API与Linux socket API之间的关系的更多相关文章

  1. JAVA Socket API与LINUX Socket API探究

    代码 这是一个带有UI界面的JAVA网络聊天程序,使用Socket连接完成通信. JAVA服务端程序 import java.io.IOException; import java.io.InputS ...

  2. 如何理解VB窗体中的scale类属性及width height属性之间的关系

    如何理解VB窗体中的scale类属性及width height属性之间的关系 VB中的SCALEHIEGT,SCALEWIDTH,与窗体中的WIDTH,HEIGHT的区别及关系是许多VB初学者难以理解 ...

  3. javascript中函数声明、变量声明以及变量赋值之间的关系与影响

    javascript中函数声明.变量声明以及变量赋值之间的关系与影响 函数声明.变量声明以及变量赋值之间有以下几点共识: 1.所有的全局变量都是window的属性 2.函数声明被提升到范围作用域的顶端 ...

  4. java 从网络Url中下载文件 (转)

    http://blog.csdn.net/xb12369/article/details/40543649/ /**       * 从网络Url中下载文件       * @param urlStr ...

  5. java 从网络Url中下载文件

    转自:http://blog.csdn.net/xb12369/article/details/40543649 /** * 从网络Url中下载文件 * @param urlStr * @param ...

  6. Socket详解-Linux Socket编程(不限Linux)

    “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...

  7. 每天进步一点点——Linux中的文件描写叙述符与打开文件之间的关系

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆能够看成是文件,文件又可分为:普通 ...

  8. java:struts2.3框架1(struts2快速配置,各文件之间的关系,基础代码简化版,XML中的通配符)

    1.struts2快速配置: A.到http://struts.apache.org下载struts2开发包struts-2.3.32-all.zip B.新建web项目并添加struts2依赖的ja ...

  9. java中关于Collection和Map相关的类&接口之间的关系

    上图(引用自)

随机推荐

  1. django----csrf跨站请求伪造 auth组件 settings源码 importlib模块

    目录 importlib模块 csrf跨站请求伪造 form表单发送 ajax发送 csrf装饰器 auth模块 如何创建超级用户(root) 创建用户 校验用户名和密码是否正确 保存用户登录状态 判 ...

  2. Spring Cloud Config入门(本地配置)

    spring cloud config 简介 Spring Cloud Config为分布式系统中的外部化配置提供服务器和客户端支持.使用Config Server,您可以在所有环境中管理应用程序的外 ...

  3. 从KafkaConsumer看看Kafka(一)

      Kafka的消息模型为发布订阅模型,消息生产者将消息发布到主题(topic)中,一个或多个消费者订阅(消费)该主题消息并消费,此模型中发布到topic中的消息会被所有消费者所订阅到,先介绍Kafk ...

  4. Java语法进阶10-泛型

    泛型 泛型:参数化的类型,即把数据类型当做参数来传递 有的地方又称为泛化的类型,用一个单个大写字母,例如<T>来代表任意类型,这个T就是泛化的类型. 泛型的好处: (1)表示某个变量的类型 ...

  5. [ASP.NET Core 3框架揭秘] 依赖注入[4]:一个Mini版的依赖注入框架

    在前面的章节中,我们从纯理论的角度对依赖注入进行了深入论述,我们接下来会对.NET Core依赖注入框架进行单独介绍.为了让读者朋友能够更好地理解.NET Core依赖注入框架的设计与实现,我们按照类 ...

  6. Python之闭包and装饰器

    闭包和装饰器是Python中非常重要的一种语法格式,在日常工作中应用非常广泛. 首先,我先为大家简单的介绍一下闭包的概念. 闭包:闭包是在函数嵌套的基础上,内层函数使用到外层函数的变量,且外层函数返回 ...

  7. MySQL基础-存储过程

    存储过程 定义:将一批为了完成特定功能的SQL语句集,根据传入的参数(也可没有),调用,完成单个sql语句更复杂的功能 存储过程思想很简单,就是SQL语句层面上的代码封装和重用 优点:1) 可封装,并 ...

  8. 从eslint规则学点JavaScript知识

    在知识星球陆续发了些eslint小知识,意在通过eslint知识去了解规则内部的原理,汇总在此: prefer-const 含义:始终用const定义你从不修改的变量,如果会被修改则使用let,永不使 ...

  9. SpringCloud路由网关Zuul

    一.什么是网关 Zuul的主要功能是路由转发和过滤器.路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务.zuul默认和Ribbon结合实现了 ...

  10. C#版本与.NET版本对应关系以及各版本的特性

    C#版本 .NET版本 发布日期 特性 C# 1.0 .NET Framework 1.0 2002-02-13 委托.事件 C# 1.1 .NET Framework 1.1 2003-04-24 ...