用java语言构建一个网络服务器,实现客户端和服务器之间通信,实现客户端拥有独立线程,互不干扰

服务器:

1.与客户端的交流手段多是I/O流的方式

2.对接的方式是Socket套接字,套接字通过IP地址和端口号来建立连接

3.(曾经十分影响理解的点)服务器发出的输出流的所有信息都会成为客户端的输入流,同时所有客户端的所有输出流都会包含在服务器的输入流中。

(即套接字即使建立连接,输入输出流都是相对自己的而言的,向外发送自己的内部的信息都用输出流,接受外部的数据都使用输入流!)

简单服务器的代码实现:

public static void main(String [] args){
  try {  //建立本地服务端,并监听6788端口号
     ServerSocket server = new ServerSocket(6788);
   //获取键盘输入,作为服务器向客户端发送的信息    Scanner reader = new Scanner(System.in);
      while (true) {
        Socket c = server.accept();
         BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
         String line;
         if ((line=br.readLine())!=null) {
           System.out.println(line);
         }
         if ((line=reader.nextLine())!=null) {
           bw.write(line);
            bw.newLine();//由于判断的时候都是nextline(),所以每次输入都必须自己给出一个换行
            bw.flush();
         }
      }

   } catch (IOException e) {
            // TODO Auto-generated catch block
        e.printStackTrace();
   }
}

与服务器链接并实现交流的客户端代码实现:

public static void main(String[] args) {
        try {      //连接到本地主机的6788端口(127.0.0.1为本地主机IP)
            Socket c = new Socket("127.0.0.1",6788);
            //获取键盘输入信息,做为向服务器发送的信息
            Scanner reader = new Scanner(System.in);

            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
            String line;
            while(true){
                if ((line = reader.nextLine())!=null) {
                    bw.write(line);
                    bw.newLine();  //客户端和服务器的读取操作都是行,所以需要自己给出换行,避免出错
                    bw.flush();
                }
                if ((line=br.readLine())!=null) {
                    System.out.println(line);
                }
            }
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

一般服务器绝不可能只为一个客户端服务,当存在很多客户端的时候,需要为每个客户端的链接建立独立的线程,使得客户端之间不会干扰,独立运行。

线程的控制实现方法有两种:

1.自定义线程类继承Thread,并重现run()方法;

2.自定义一个普通类,实现Runnable接口(本文采用此方法实现多线程控制)

具体代码实现:

//服务器的代码public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(6666);

            while (true) {          //一直监控是否有客户端连接
                Socket s = serverSocket.accept();
                //每当有客户端连接时,为每个客户端开辟独立线程执行
                Thread ch = new Thread(new ThreadManager(s));
                ch.start();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

实现线程的自定义类:

public class ThreadManager implements Runnable{

    private Socket socket;

    public ThreadManager(Socket s){
        this.socket = s;
    }
    @Override
    public void run() {
        BufferedWriter bw;
        BufferedReader br;
        try {
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
           //连续不断地向客户端发送信号,数字不断在变化,若客户端先后链接,发送的信息独立则独立线程实现        for(int i = 0; i<1000000;i++){        bw.write(i+"````````````````");        bw.newline();        bw.flush();        }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

用来接收服务端的客户端代码实现:

public static void main(String[] args) {
        try {        //链接到本地的6666端口
            Socket s = new Socket("127.0.0.1",6666 );

            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            String line;
        while(true){
            while ((line = br.readLine())!=null) {
                //将服务器发送的信息输出          System.out.println(line);
            }
        }

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

注:为方便观察,可在cmd窗口中启动客户端的代码,重复打开几个dos窗口,并链接到本地的6666端口,就会收到服务器发送过来的递增的数字,所有的dos窗口都启动后,可以发现每个窗口的数字增长的程度并不相同,但都一直在运行,互不干扰,至此,为客户端创立的独立线程实现。

注:还有很多的网络知识未曾收集和整理,当自己再次看到这里的时候,记得补足基础部分,以再次夯实基础,加强回忆。

时间: 2024-10-21 08:39:46

用java语言构建一个网络服务器,实现客户端和服务器之间通信,实现客户端拥有独立线程,互不干扰的相关文章

iOS—网络实用技术OC篇&amp;网络爬虫-使用java语言抓取网络数据

网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一片文章已经介绍我们可以使用两个方式来抓取网络数据实现网络爬虫,并且大致介绍了一下怎么使用正则表达式去实现数据的抓取 由于笔者曾经学过一段时间java和android相关的技术,今天就讲讲怎么使用java去抓取网络数据,关于Python有机会等笔者好好研究一下再来分享,但其实会一种就可以,除非你的需求

iOS开发——网络实用技术OC篇&amp;网络爬虫-使用java语言抓取网络数据

网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一片文章已经介绍我们可以使用两个方式来抓取网络数据实现网络爬虫,并且大致介绍了一下怎么使用正则表达式去实现数据的抓取 由于笔者曾经学过一段时间java和android相关的技术,今天就讲讲怎么使用java去抓取网络数据,关于Python有机会等笔者好好研究一下再来分享,但其实会一种就可以,除非你的需求

基于Java语言构建区块链(一)—— 基本原型

引言 区块链技术是一项比人工智能更具革命性的技术,人工智能只是提高了人类的生产力,而区块链则将改变人类社会的生产关系,它将会颠覆我们人类社会现有的协作方式.了解和掌握区块链相关知识和技术,是我们每位开发人员必须要去做的事情,这样我们才能把握住这波时代趋势的红利. 本文将基于Java语言构建简化版的blockchain,来实现数字货币. 创建区块区块链是由包含交易信息的区块从后向前有序链接起来的数据结构.区块被从后向前有序地链接在这个链条里,每个区块都指向前一个区块.以比特币为例,每个区块主要包含

R语言构建蛋白质网络并实现GN算法

R语言构建蛋白质网络并实现GN算法 1.蛋白质网络的构建 我们使用与人类HIV相关的蛋白质互作数据hunam-HIV PPI.csv来构建这个蛋白质互作网络. 在R中,我们可以从存储在R环境外部的文件读取数据.还可以将数据写入由操作系统存储和访问的文件. R可以读取和写入各种文件格式,如:csv,excel,xml等. 想要读取csv文件,我们需要: 设置工作目录 读取CSV文件 代码如下: setwd("/Users/.../Documents/...") data <- re

JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七层:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层 TCP/IP协议 TCP/IP是一系列网络通信协议的统称,其中最核心的两个协议是TCP和IP.TCP称为传输控制协议,IP称为互联网络协议. 网络分层除了OSI模型分层,还有TCP/IP模型分层,将网络划分为四层,应用层.传输层.网际层

如何用 Swift 语言构建一个自定控件

(via:破船之家,原文:How To Make a Custom Control in Swift) 用户界面控件是所有应用程序重要的组成部分之一.它们以图形组件的方式呈现给用户,用户可以通过它们与应用程序进行交互.苹果提供了一套控件, 例如 UITextField,UIButton,UISwitch.通过工具箱中的这些已有控件,我们可以创建各式各样的用户界面. 然而,有时候你希望界面做得稍微的与众不同,那么此时苹果提供的这些控件就无法满足你的需求. 自定义控件,除了是自己构建二外,与苹果提供

用Java语言编写一个简易画板

讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目需要满足怎样的需求. 那么,画板需要满足怎样的需要呢?换句话说,在画板上,我们应该赋予它什么功能呢?从我们熟悉的画板来看,我们需要实现诸如铅笔.橡皮.喷枪.刷子的功能,我们可以画出一些规则的图形,比如直线.矩形.圆.最好我们还能调整画笔的颜色和粗细.以上,我们希望的是,当我们点击一个按钮的时候,我们

用java语言实现一个观察者模式

观察者模式(也被称为发布/订阅模式)提供了避免组件之间紧密耦合的另一种方法,它将观察者和被观察的对象分离开.在该模式中,一个对象通过添加一个方法(该方法允许另一个对象,即观察者注册自己)使本身变得可观察.当可观察的对象更改时,它会将消息发送到已注册的观察者.这些观察者收到消息后所执行的操作与可观察的对象无关这种模式使得对象可以相互对话,而不必了解原因.Java语言与C#语言的事件处理机制就是采用的此种设计模式. 例如,用户界面(同一个数据可以有多种不同的显示方式)可以作为观察者,业务数据是被观察

基于Java语言构建区块链(三)—— 持久化 &amp; 命令行

引言上一篇 文章我们实现了区块链的工作量证明机制(Pow),尽可能地实现了挖矿.但是距离真正的区块链应用还有很多重要的特性没有实现.今天我们来实现区块链数据的存储机制,将每次生成的区块链数据保存下来.有一点需要注意,区块链本质上是一款分布式的数据库,我们这里不实现"分布式",只聚焦于数据存储部分. 给大家推荐一个java内部学习群:725633148,进群找管理免费领取学习资料和视频.没有错就是免费领取!大佬小白都欢迎,大家一起学习共同进步! 数据库选择 到目前为止,我们的实现机制中还