基于Tcp的简单服务器

  • UDP协议无连接类似于发微信
  • TCP协议有链接类似于打电话
  • 所以基于TCP的服务器先要到内核中获取一个TCP连接,UDP不需要获取连接
  • TCP的连接管理是由操作系统的内核来管理的,客户端和服务器建立连接的过程中,完全由内核来进行负责。负责程序的代码感知不到
  • TCP的来连接管理需要先描述在组织
    • 描述:通信的五元组
    • 组织:使用一个阻塞队列来组织若干个连接对象
  • 代码中调用这个accept方法就是从阻塞队列当中获取一个链接对象(在应用程序中的化身就是Socket对象)
  • 后续数据读写都是根据这个clientSocket这个对象来进行展开的
  • 如果都服务器启动之后,没有客户端建立连接,此时代码中调用accpt方法就会阻塞,阻塞到真的有客户端建立连接为止。
  • 简单的TCP服务器
package com.zb.network.test;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;/*** @Description: 基于Tcp的简单服务器* @Author:啵啵啵啵啵啵唧~~~* @Date:2022/5/4*/
public class TcpEchoServer {/*** 1、初始化服务器* 2、进入主循环*  1.先去从内核当中获取到一个TCP连接*  2.处理这个TCP连接*   a.读取请求并解析*   b.根据请求计算响应*   c.把响应写回给客户端*//*** 创建于给serverSocket对象*/private ServerSocket serverSocket = null;/*** 构造方法,初始化serverSocket对象** @param port* @throws IOException*/public TcpEchoServer(int port) throws IOException {//这个操作和UDP类似需要绑定端口号serverSocket = new ServerSocket(port);}/*** 启动服务器** @throws IOException*/public void start() throws IOException {System.out.println("服务器启动");while (true) {//1.先从内核当中获取一个TCP连接,当客户端没有连接过来的时候,accept就会陷入阻塞Socket clientSocket = serverSocket.accept();//2.处理这个链接processConnection(clientSocket);}}/*** 处理连接的方法* 一个连接中客户端和服务器之交互一次么?* 服务器的处理方式有两种* 1.一个连接中客户端和服务器只交互一次,交互完毕,就断开连接(短连接)* 2.一个连接中,客户端和服务器之间交互N次,直到满足一定的条件再断开连接(长连接)* 其中长连接的效率小队来说效率高一些** @param clientSocket*/private void processConnection(Socket clientSocket) {System.out.printf("[%s:%d]客户端上线\n", clientSocket.getInetAddress().toString(),clientSocket.getPort());//通过clientSocket来和客户端交互,先做好准备工作,获取到clientSocket中的流对象try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()))){//此处实现一个长连接的版本,一次处理的过程当中,需要处理多个请求和响应//当客户端断开连接的时候,服务器再去调用readLine或者write方法都会触发异常(IOException)while (true) {//1.读取请求并解析//此处暗含一个重要的信息,客户端发的数据必须是一个按行发送的数据(每条数据一行)String request = bufferedReader.readLine();//2.根据请求计算响应String response = process(request);//3.把响应写回到客户端(客户端按行来读)bufferedWriter.write(response + "\n");//手动刷新缓冲区bufferedWriter.flush();System.out.printf("[%s:%d] req: %s; resp: %s\n", clientSocket.getInetAddress().toString(),clientSocket.getPort(), request, response);}} catch (IOException e) {System.out.printf("[%s:%d]客户端下线\n", clientSocket.getInetAddress().toString(),clientSocket.getPort());}}/*** 根据请求计算响应** @param request* @return*/private String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}

  • TCP客户端
package com.zb.network.test;import java.io.*;
import java.net.Socket;
import java.util.Scanner;/*** @Description:* @Author:啵啵啵啵啵啵唧~~~* @Date:2022/5/4*/
public class TcpEchoClient {//1.启动客户端(一定不要绑定端口号)和服务器建立连接//2.进入主循环// a.读取用户输入的内容// b.构造一个请求发送给服务器// c.读取服务器响应的数据// d.把响应数据显示到界面上private Socket socket = null;/*** 实例化socket* @param serverIp* @param serverPort* @throws IOException*/public TcpEchoClient(String serverIp, int serverPort) throws IOException {//此处实例化就是建立TCP连接(三次握手的过程)socket = new Socket(serverIp,serverPort);}public void start(){System.out.println("客户端启动");Scanner sc = new Scanner(System.in);try(  //获取两个流对象BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {while (true){//读取用户输入的内容System.out.print("->");String request = sc.nextLine();if ("exit".equals(request)){break;}//2.客户端构造请求并发送.此处+\n为了和服务器中的readLine向对应bufferedWriter.write(request + "\n");//刷新缓存bufferedWriter.flush();//3.客户端读取响应数据。String response = bufferedReader.readLine();//4.把响应数据显示到界面上.System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);client.start();}}

注意

  • UDP中必须用receive和send.传输数据的基本单位是DatagramPacket对象.[面向数据报]
  • TCP中必须用read和write,传输数据的基本单位是字节.[面向字节流 ]
  • 他们传输协议上的差异导致代码的差异
  • Tcp要刷新缓冲区的作用
  • //--------------------服务器刷新缓冲区-----------------------//3.把响应写回到客户端(客户端按行来读)bufferedWriter.write(response + "\n");//手动刷新缓冲区bufferedWriter.flush();
    //----------------------客户端刷新缓冲区----------------------//2.客户端构造请求并发送.此处+\n为了和服务器中的readLine向对应bufferedWriter.write(request + "\n");//刷新缓存bufferedWriter.flush();
    

解决Tcp连接只能有一个客户端连接服务器的问题

  • 原因就是accept方法的调用,调用几个accept方法就处理几个连接,在代码中出现的问题就是由于为了要实现长连接,导致循环退不出去,导致accept方法无法正常调用,所以只能有一个客户端和服务器进行连接
  • 解决方法就是使用多线程,用一个线程专门来调用accept方法从而实现并发操作,这样既可以实现长连接又可以正常调用accept方法,其实单线程的方式也可以解决,使用IO多路复用即可,而且十分高效,但是比较麻烦
  • 这样就可以让多个客户端同时连接服务器

基于TCP的简单服务器相关推荐

  1. C++基于TCP/IP简单的客户端、服务器通信程序实例

    本篇文章实现了一个基于TCP 的一个非常简单的客户/服务器通信程序实例.该程序中通讯协议使用的是面向连接的TCP协议SOCK_STREAM, 服务器的ip地址为本地地址即: 127.0.0.1,端口号 ...

  2. 基于 TCP Socket 的服务器与客户端的简单连接

    简单的讲下流程: 1. 服务器会创建一个监听 socket, 用来监听客户端的连接请求,接着配置一下监听 socket 的 IP.port.protocol 2. 绑定配置好的信息 以及监听 sock ...

  3. Android 端的基于TCP的小型服务器_超级简单

    服务端代码: HttpServer: package example.com.httpserver;import android.graphics.Bitmap; import android.gra ...

  4. 基于TCP实现简单网络计算器

    这里我们需要简单实现网络版的计算器,我打算让它具有计算加法,减法,乘法,除法,还有取模 的功能. 例如(加法),我们需要实现一个服务器版的加法器,我们需要客户端把要计算的两个加数发过去,然后由服务端进 ...

  5. Java案例:基于TCP的简单聊天程序

    文章目录 一.如何实现TCP通信 二.编写C/S架构聊天程序 (一)编写服务器端程序 - Server.java (二)编写客户端程序 - Client.java (三)测试服务器端与客户端能否通信 ...

  6. 江南大学C语言大作业,TCPIP大作业基于TCP的网络通信编程C语言版(江南大学).doc...

    TCPIP大作业基于TCP的网络通信编程C语言版(江南大学).doc TCP/IP协议编程大作业 课题名称 基于TCP的网络通信 专 业 计算机科学与技术 班 级 计算机1206 学 号 103041 ...

  7. 网络编程——基于TCP协议的通讯录【课程设计】

    网络编程--基于TCP协议的通讯录[课程设计] 本文目录 网络编程--基于TCP协议的通讯录[课程设计] 一.设计题目和要求 设计目标: 课程设计系统组成及模块功能: 二.设计内容 服务端 客户端 S ...

  8. 打印服务器协议,基于TCP/IP协议的嵌入式网络打印服务器设计

    摘要: 随着电子技术和计算机网络技术的发展,嵌入式系统在家庭和工业的各个领域都得到了广泛的应用,各种信息家电,网络设备以及工业控制领域都出现了嵌入式系统的身影,其数量已经远远超过了各种通用计算机.但是 ...

  9. Linux系统下实现基于TCP/IP协议的简单Socket通信

    Linux系统下实现基于TCP/IP协议的简单Socket通信 网络套接字Socket Socket概念 主机字节序和网络字节序 Sockaddr地址结构 Socket实现客户端.服务端通信 服务端程 ...

最新文章

  1. 冰刃——IceSword
  2. 使用阿里云的maven私服的setting.xml, 提高maven项目jar下载速度
  3. 使用sed,awk将love转换成LOVE,将CHINA转换成china
  4. C++ Primer 5th笔记(chap 14 重载运算和类型转换)输入和输出运算符
  5. extern使用说明
  6. 【华为云技术分享】GitHub联合开发
  7. html5学习笔记---05.JavaScript 中的面向对象,继承和封装
  8. mockit学习(一)
  9. 自定义日历控android,android 一个简单的自定义日历控件,让你掌控时间
  10. Flash CS4学习笔记1
  11. 项目采集自动刷新 php,PHP168 CMS自动采集-PHP168 CMS自动更新-齐博CMS站群管理系统...
  12. kafka错误代码解释
  13. Vue项目实战:订单列表页面实现
  14. DEVc++迷你世界0.10.0
  15. 浅聊一下Java中的char类型
  16. 小米9私密相册怎么找_小米手机私密相册怎么用?怎么打开查看?
  17. 耦合(六种)与 内聚(七种)—《软件工程与计算》笔记
  18. 远程桌面连接出现身份验证错误。要求的函数不受支持。这可能是由于CredSSP加密数据库修正。
  19. 23.Odoo产品分析 (三) – 人力资源板块(4) – 招聘流程(1)
  20. cct考试模拟试题c语言,计算机一级(CCT)考试模拟题

热门文章

  1. SSD网络接口介绍(包含完整代码)
  2. STM32F103ZG单片机解密确保成功 ST芯片解密
  3. 阿里云服务器快速购买、自定义购买、通过活动购买图文教程
  4. 中国云计算产业2016年度点评
  5. python泰坦尼克号数据预测_泰坦尼克号幸存者预测 python 详解
  6. 屏幕正中间浮窗html,HTML 纯css浮窗居中和打开or关闭
  7. 对 Groovy 进行单元测试
  8. 区块链游戏- Solcery(Summoner 召唤者)
  9. 计算机关机时出现蓝屏,关机蓝屏,教您电脑关机蓝屏怎么解决
  10. 修改pc端浏览器的滚动条的默认样式