编写简单的服务器应用程序

编写服务器应用程序需要用到一对Socket。他们是一个会等待用户请求(当用户创建Socket是)的ServerSocket和与用户进行通信用的Socket。

工作方式:

1. 服务器应用程序对特定端口创建出ServerSocket。

ServerSocket serverSocket = new ServerSocket(8080);

2. 客户端对服务器应用程序建立Socket连接。

Socket socket = new Socket("127.0.0.1", 8080);

3. 服务器创建出与客户端通信的新的Socket。

Socket socket = serverSocket.accept();

下面是一个简单的聊天室应用程序(这个版本只完成了客户端向服务端发送数据)

服务端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;public class DailyAdviceServer {String[] adviceList = { "愿得一人心,白首不相离。", "天长地久有时尽,此恨绵绵无绝期。","东边日出西边雨,道是无晴却有晴。", "曾经沧海难为水,除却巫山不是云。", "两情若是久长时,又岂在朝朝暮暮。","庄生晓梦迷蝴蝶,望帝春心托杜鹃。" };public static void main(String[] args) {new DailyAdviceServer().go();}private void go() {try {ServerSocket serverSocket = new ServerSocket(8888);// ServerSocket会监听客户端对这台机器在8888端口上的请求System.out.println("服务器启动。。。");/* 服务器进入无限循环监听客户端请求 */while (true) {Socket socket = serverSocket.accept();// 该方法会停下来,直到满足要求才会继续/* 向客户端发送数据 */PrintWriter printWriter = new PrintWriter(socket.getOutputStream());// 使用Socket连接来送出真言信息String advice = getAdvice();printWriter.println(advice);System.out.println("欢迎信息:" + advice);/* 接收客户端数据 */BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String info = null;while ((info = bufferedReader.readLine()) != null) {System.out.println("客户端数据:" + info);}}} catch (IOException e) {System.out.println("服务器错误!");System.exit(-1);}}private String getAdvice() {return adviceList[new Random().nextInt(adviceList.length)]; // 随即返回字符串数组中的一首诗}}

客户端:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;public class SimpleClient {private PrintWriter printWriter;private JTextField textField;public static void main(String[] args) {new SimpleClient().go();}private void go() {/* 图形用户界面的绘制 */JFrame frame = new JFrame("一个简单的客户端程序");JPanel panel = new JPanel();textField = new JTextField("请输入需要发送的信息");JButton button = new JButton("发送");button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {printWriter.println(textField.getText());printWriter.flush();textField.setText(""); // 每次发送之后清空输入textField.requestFocus();//请求焦点}});panel.add(textField);panel.add(button);frame.getContentPane().add(panel, BorderLayout.CENTER);frame.setVisible(true);frame.pack();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setUpNetwork();}private void setUpNetwork() {try {Socket socket = new Socket(InetAddress.getLocalHost(), 8888);printWriter = new PrintWriter(socket.getOutputStream());System.out.println("连接已建立!");} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}

运行结果:

以上代码有一个很明显的bug,即服务端只能接收一个客户端的输入。可以引入线程来解决。
更好的版本:
服务器:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;public class VerySimpleChatServer {ArrayList clientOutputStreams;public class ClientHandler implements Runnable {BufferedReader bufferedReader;Socket socket;public ClientHandler(Socket socket) {this.socket = socket;try {bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {String message;try {while ((message = bufferedReader.readLine()) != null) {System.out.println("客户端发送数据:" + message);tellEveryone(message);}} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {new VerySimpleChatServer().go();}private void go() {clientOutputStreams = new ArrayList();try {ServerSocket serverSocket = new ServerSocket(8888);while (true) {Socket clientSocket = serverSocket.accept();PrintWriter printWriter = new PrintWriter(clientSocket.getOutputStream());clientOutputStreams.add(printWriter);Thread t = new Thread(new ClientHandler(clientSocket));t.start();System.out.println("已连接。。");}} catch (IOException e) {e.printStackTrace();}}private void tellEveryone(String message) {Iterator iterator = clientOutputStreams.iterator();while (iterator.hasNext()) {PrintWriter printWriter = (PrintWriter) iterator.next();printWriter.println(message);printWriter.flush();}}}

客户端:

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.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;public class SimpleChatClient {JTextField out;PrintWriter printWriter;JTextArea in;public BufferedReader bufferedReader;public static void main(String[] args) {new SimpleChatClient().go();}private void go() {/* 界面和事件 */JFrame frame = new JFrame("聊天室-客户端");JPanel panel = new JPanel();in = new JTextArea(10, 50);in.setLineWrap(true);in.setWrapStyleWord(true); // 单词空白处换行in.setEditable(false);JScrollPane scrollPane = new JScrollPane(in);scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);out = new JTextField("请输入你要发送的信息!", 50);JButton button = new JButton("发送");button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {printWriter.println(out.getText());printWriter.flush(); // 这个是必须要有的out.setText("");out.requestFocus();}});panel.add(out);panel.add(button);panel.add(new JLabel("服务器端信息:"));panel.add(scrollPane);setUpNetWork();/* 启动新的线程,以内部类作为任务,此任务是读取服务端的socket串流,显示在文本域 */Thread readerThread = new Thread(new IncomingReader());readerThread.start();frame.getContentPane().add(panel);frame.setVisible(true);frame.pack();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}private void setUpNetWork() {Socket socket;try {socket = new Socket(InetAddress.getLocalHost(), 8888);bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));printWriter = new PrintWriter(socket.getOutputStream());System.out.println("建立连接。。。");} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public class IncomingReader implements Runnable {@Overridepublic void run() {String message;try {while ((message = bufferedReader.readLine()) != null) {System.out.println("服务器信息:" + message);in.append(message + "\n");}} catch (IOException e) {e.printStackTrace();}}}
}

运行结果:

基于UDP的聊天室的实现。

对于UDP编程,java提供了2个类给予支持。他们分别是DatagramSocket和DatagramPacket。UDP是面向无连接的,发送端和接收端哪个先启动并没有区别。在发送端在构造DatagramPacket(数据包)的时候需要为其指定目的主机和目标端口。在接收方我们只需要在初始化DatagramSocket的时候指定监听端口(发送端需要发送的端口)即可。然后通过此DatagramSocket的receive方法取得数据包,用数据包中的getData方法取得内容。

发送端Send.java

public class Send implements Runnable {DatagramSocket ds;int descport;public Send(DatagramSocket ds, int descport) {System.out.println("发送端已经启动。。。。。。。。。。。。。。。");this.ds = ds;this.descport = descport;}@SuppressWarnings("resource")@Overridepublic void run() {while (true) {System.out.println("请输入要发送的数据:");Scanner scanner = new Scanner(System.in);try {while (scanner.hasNext()) {System.out.println("请输入要发送的数据:");String line = scanner.nextLine();byte[] buf = line.getBytes();DatagramPacket dp = new DatagramPacket(buf, buf.length,InetAddress.getLocalHost(), descport); // 数据报的终点是127.0.0.1:8888ds.send(dp);if ("quit".equals(line))return;scanner = new Scanner(System.in);}} catch (IOException e) {throw new RuntimeException("发送失败!");}}}public static void main(String[] args) throws SocketException {// 对于发送方来说,从哪个端口发出数据报并不重要,重要的是数据报要发送到哪里new Thread(new Send(new DatagramSocket(1111), 8888)).start(); // 发送端127.0.0.1:1111,目的127.0.0.1:8888}}
接收端Receive.java
public class Receive implements Runnable {DatagramSocket ds;public Receive(DatagramSocket ds) {System.out.println("接收端已经启动。。。。。。。。。。。。。");this.ds = ds;}@Overridepublic void run() {while (true) {byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf, buf.length);try {ds.receive(dp);String data = new String(dp.getData(), 0, dp.getLength());if ("quit".equals(data)) {return;}System.out.println("收到来自:" + dp.getSocketAddress() + "的数据:"+ data);} catch (IOException e) {throw new RuntimeException("接收失败!");}}}public static void main(String[] args) throws SocketException {// 对于接收端来说,只需要绑定接收端口即可,不需要关系数据的来源new Thread(new Receive(new DatagramSocket(8888))).start(); // 接收端在127.0.0.1:8888端口监听}}

HeadFirstJava学习心得——网络编程相关推荐

  1. python网络编程视频教程_Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密)...

    Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密) 全面理解BIO/NIO/AIO 网络层编程,是每一个开发者都要面对的技术.课程为解决大家学习网络层知识的难题, ...

  2. python网络编程要学吗_总算发现如何学习python网络编程

    为了提高模块加载的速度,每个模块都会在__pycache__文件夹中放置该模块的预编译模块,命名为module.version.pyc,version是模块的预编译版本编码,一般都包含Python的版 ...

  3. openfoam学习心得——openfoam编程进阶

    openfoam学习心得--openfoam编程重新学 1.OpenFOAM编程入门:setRootCase都干了些啥? setRootCase都干了些啥 2.blockMesh > log.b ...

  4. python编程入门指南怎么样-学习python网络编程怎么入门

    第一部分底层网络学习 Python提供了访问底层操作系统Socket接口的全部方法,需要的时候这些接口可以提供灵活而强有力的功能. (1)基本客户端操作 在<python 网络编程基础>一 ...

  5. Python学习笔记:网络编程

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  6. linux java socket编程_深入学习socket网络编程,以java语言为例

    了解java的socket编程与Linux Socket API之间的关系 一.java的网络编程 1.socket原理 socket通信就是通过IP和端口号将两台主机建立连接,提供通信.主机A的应用 ...

  7. Proxy源代码分析--谈谈如何学习linux网络编程

    Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该是 ...

  8. Java学习之网络编程实例

    转自:http://www.cnblogs.com/springcsc/archive/2009/12/03/1616413.html 多谢分享 网络编程 网络编程对于很多的初学者来说,都是很向往的一 ...

  9. 初学者怎么自学python编程_学习python网络编程怎么入门

    第一部分底层网络学习 Python提供了访问底层操作系统Socket接口的全部方法,需要的时候这些接口可以提供灵活而强有力的功能. (1)基本客户端操作 在<python 网络编程基础>一 ...

  10. java 学习笔记-网络编程(八)

    网络编程 标签:学习各种网络协议的桥梁 什么是计算机网络 计算机网络的作用:资源共享和信息传递. 计算机网络的组成: a) 计算机硬件:计算机(大中小型服务器,台式机.笔记本等).外部设备(路由器.交 ...

最新文章

  1. 面试官:你们Redis故障过吗,怎么解决?
  2. streaming优化:spark.default.parallelism调整处理并行度
  3. 易语言---时间操作
  4. 回溯算法 | 追忆那些年曾难倒我们的八皇后问题
  5. 【Tools】RDB打包工具详解
  6. 安装CentOS 7 遇到的坑
  7. 阿里的事前验尸_(不太完全)100天的代码-验尸
  8. CSDN-Markdown-图片设置(大小,居中)
  9. linux 定时java程序,Linux操作系统上定时运行Java程序的方法
  10. Cookie与Session相关学习笔记
  11. 用javascript实现有效时间的控制,并显示要过期的时间
  12. 我的第一个MPI程序:利用矩形规则计算pi
  13. MFC9.0 Outlook控件的标题显示无法改动
  14. java动态是如何根据实体建表_传入Java对象 自动创建动态表 并录入数据
  15. Django2.1迁移数据库出错
  16. 11.2 RS232通信接口
  17. 基于python的异方差检验_异方差检验及解决方法
  18. java 如何调用大漠插件_java通过jaboc调用dll(大漠插件)遇到的坑,变参指针传参问题...
  19. matlab逆变换法产生随机数_用matlab产生随机数
  20. canvas画不规则图形

热门文章

  1. 免费下载遥感数据的网址
  2. 开源的工业软件-面向生产控制环节
  3. Smart3D运行过程中遇到的问题(持续更新)
  4. Visual Studio中实用工具VAssistX
  5. 小米路由器刷 linux,小米路由器刷入Padavan系统
  6. Flutter IM 极光
  7. 《离散数学》题库大全及答案
  8. W3CSchool离线文档下载
  9. pycharm汉化包下载是某度网盘再现江湖?!不存在的!!真相就是如此简单~
  10. 网页设计期末复习 选择+简答+大题