web发展中通信的方式有哪些呢? - 编程思维

Web发展中通信方式

  • 简单通信
  • 不同请求
  • 复杂请求

案例实操

1 简单通信

回顾 Socket 编程给我们最大的感受,是可以在多台电脑之间进行数据的传输,这就是网络编程的开端和基础,通过客户端请求服务器端通信,直观了解 Web 编程。

Server

/**

  • 服务端,接收客户端请求并给出简单的响应
  • @author Cushier

*
*/
public class Server {

public static void main(String[] args) throws IOException{
// 创建服务器,指定端口ServerSocket(int port)
ServerSocket socket = new ServerSocket(8888);
// 接收客户端连接
Socket client = socket.accept();
System.out.println("**");
// 获取数据的输入流
InputStream is = client.getInputStream();
// 使用缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = "";
while ((msg = br.readLine()) != null) {
System.out.println(msg);
}
br.close();
}

}

Client

/**

  • 客户端:向服务器发送请求,并发送简单的消息
  • @author Cushier

*
*/
public class Client {

public static void main(String[] args) throws UnknownHostException, IOException {
// 创建客户端 必须指定服务器+端口
Socket client = new Socket("localhost", 8888);
// 发送消息 请求资源
// 获取输出流
OutputStream os = client.getOutputStream();
// 使用缓冲字符输出流
BufferedWriter br = new BufferedWriter(new OutputStreamWriter(os));
// 写出消息,发送内容
String msg = "Hello, I am Client, I need some resources";
br.write(msg);
br.close();
}

}

服务端控制台:

从上面的例子总结通信条件如下:

  1. 需要有服务器端(server):等待被请求,需要暴露 ip 和 port
  2. 需要有客户端(client):主动发起请求,知晓服务端的 ip 和 port
  3. 通信规则(协议):TCP/IP 协议

    ip 用于定位计算机;端口号(定位程序),用于标识进程的逻辑地址,不同进程的标志;有效端口:0~65535,其中 0~1024 由系统使用或者保留端口,开发中建议使用 1024 以上的端口。

2 不同请求

Client

/**

  • 客户端:向服务器发送请求,发送不同的请求
  • @author Cushier

*
*/
public class Client {

public static void main(String[] args) throws IOException {
// 通过系统默认类型的 SocketImpl 创建未连接套接字
Socket socket = new Socket();
// 此类实现 IP 套接字地址(IP 地址 + 端口号)。它还可以是一个对(主机名 + 端口号),在此情况下,将尝试解析主机名
SocketAddress address = new InetSocketAddress("localhost", 8898);
// 将此套接字连接到服务器,并指定一个超时值。或者不指定超时时间
socket.connect(address, 1000);
OutputStream os = socket.getOutputStream();
os.write("time".getBytes());
os.flush();
socket.close();
}

}

Server

/**

  • 服务端
  • public class ServerSocketextends Object:此类实现服务器套接字。
  • 服务器套接字等待请求通过网络传入。
  • 它基于该请求执行某些操作,然后可能向请求者返回结果。
  • @author Cushier

*
*/
public class Server {

public static void main(String[] args) throws IOException {
// 创建绑定到特定端口的服务器套接字。
ServerSocket server = new ServerSocket(8898);

// Socket accept() 侦听并接受到此套接字的连接。
Socket client = server.accept();
System.out.println("接收到连接");

InputStream is = client.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] req = new byte[1024];
// 接收客户端请求
int len = bis.read(req);
String reqStr = new String(req, 0, len);
System.out.println(reqStr);
if (reqStr.equals("money")) {
System.out.println("here's the money");
} else if (reqStr.equals("time")) {
System.out.println("you have so much time");
}
client.close();
server.close();
}

}

服务端控制台:

3 复杂请求

Client

/**

  • 客户端
  • @author Cushier

*
*/
public class Client {

public static void main(String[] args) throws IOException {
// 通过系统默认类型的 SocketImpl 创建未连接套接字
Socket socket = new Socket();
// 此类实现 IP 套接字地址(IP 地址 + 端口号)。它还可以是一个对(主机名 + 端口号),在此情况下,将尝试解析主机名
SocketAddress address = new InetSocketAddress("localhost", 8898);
// 将此套接字连接到服务器,并指定一个超时值。或者不指定超时时间
socket.connect(address, 1000);

OutputStream os = socket.getOutputStream();
os.write("money".getBytes());
os.flush();
// 接收响应,显示结果
InputStream is = socket.getInputStream();
byte[] result = new byte[1024];
int len = is.read(result);
String resultStr = new String(result, 0, len);
System.out.println(resultStr);
socket.close();
}

}

Server

/**

  • 服务端
  • @author Cushier

*
*/
public class Server2 {

public static void main(String[] args) throws IOException {
// 创建绑定到特定端口的服务器套接字。
ServerSocket server = new ServerSocket(8898);

// Socket accept() 侦听并接受到此套接字的连接。
Socket client = server.accept();
System.out.println("接收到连接");
InputStream is = client.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] req = new byte[1024];
// 接收客户端请求
int len = bis.read(req);
String reqStr = new String(req, 0, len);
System.out.println(reqStr);
// 将接收到的请求封装成对象,传送给请求的类
MyRequest request = new MyRequest();
MyResponse response = new MyResponse();

OutputStream os = client.getOutputStream();
if (reqStr.equals("money")) {
// 根据请求的信息,构造处理的类
MyServlet s1 = new ServletMoney();
s1.service(request, response);
// 通过client的响应,将结果响应回客户端
os.write("here's the money".getBytes());
os.flush();
} else if (reqStr.equals("time")) {
// 根据请求的信息,构造处理的类
MyServlet s2 = new ServletTime();
s2.service(request, response);
// 通过client的响应,将结果响应回客户端
os.write("you have somuch time".getBytes());
os.flush();
}
client.close();
server.close();
}

}

/*

  • 我是一个有要求的人,你请求的这个资源必须是满足我要求格式的类,作用:防止混乱,方便调用 这是我的标准

*/
interface MyServlet {
void service(MyRequest req, MyResponse resp);
}

class ServletMoney implements MyServlet {
@Override
public void service(MyRequest req, MyResponse resp) {
// 做出力所能及的处理
}
}

class ServletTime implements MyServlet {
@Override
public void service(MyRequest req, MyResponse resp) {
// 做出力所能及的处理
}
}

/*

  • 请求信息都按规律封装在该对象

*/
class MyRequest {
}

class MyResponse {
}

服务端控制台: 客户端控制台:

随着客户需求越来越复杂,需要的功能越来越多,我们的服务器端需要处理的请求越来越多,需要区分不同的请求,还需要按照不同请求进行请求数据的提取以及资源的分配和运算还有逻辑的处理,最后还需要响应给客户端,这就使得服务器端代码越来越复杂,实现越来越困难

根据以往的经验,双方进行通信只需要遵循一定的规则就可以很明确地知道各部分数据的含义,于是出现了网络更上层的应用协议(后面讲的 HTTP 协议),规定服务器端和客户端通信的规则。

客户端请求服务器端和服务器端响应客户端,都按照固定的规则,那么接收请求和响应数据这部分操作就可以固定下来,交给特定的一段代码来执行,从而减少服务器端的代码量,于是出现了接下来说的服务器

扩展

服务器的出现

当客户端请求的资源越来越丰富,需求越来越复杂,程序的核心就应该放在解决业务和计算响应数据上,于是出现了服务器统一接收客户端数据进行处理并分发到不同的资源,由各个资源进行处理,最后结果交由服务器响应。

从上面的描述可以发现,现在所说的服务器只是负责接收请求,对请求进行分发,以及最后将获取的数据进行相应的固定框架,至于数据怎么计算得出还得根据具体的业务需求编写(填充)代码。在没有业务需求的情况下就能将服务器准备出来,现在市面上的服务器有很多,比较常用的有:Tomcat、JBOOS、IBM 的 WebSphere、BEA的 WebLogic 以及 Apache 等。

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://segmentfault.com/a/1190000038726949

五步带你探究爬虫爬取视频弹幕背后的真相,附爬虫实现源码 - 编程思维

前言好久没更新,不知道各位粉丝有没有等着急,没办法,这不是要到年底了啊,又要开始准备一年一度的工作汇报了,咱到现在也不知道这玩意到底有什么用,反正就是每一家公司都需要这么个玩意,其中,最让我头疼的就是这个未来展望的环节,我要是能预测未来我不早就去买彩票发大财,还在这给你写什么规划。但是谁让你是老大呢,哎,所以,没办法,

不想被毕设打垮的应届生,通过github上找到了“宝藏” - 编程思维

前言对于程序员而言,GitHub是一个宝藏男孩,为什么大家会把自己的辛苦写出来的源码挂到GitHub上呢?拿出卖钱它不香吗?其实对于这个问题,下面这张图做了很好的阐释:说到底,开源是利他利己的,比如音乐是分享给大家免费听的,听音乐本身并不需要钱,听电台就是。你想听什么就听什么,还可以用各种音效工具给增强你的视听享受,或

推荐5款最好用的内网穿透工具 - 编程思维

公众号开发过程中,频繁修改线上代码,开发过程比较繁琐,同时一旦出错将会影响到线上的其他正常业务,因此搭建一个微信公众号开发的本地环境能达到不影响线上业务的同时调试代码。这里推荐几款非常好用的内网穿透工具,如有其它推荐,欢迎补充1.frpfrp 是一个高性能的反向代理应用,可以帮助您轻松地进行内网穿透,对外网提供服务,支

面试一家小公司,被问了 1 个小时并发编程。。全程已记录! - 编程思维

最近有读者投简历去一家小公司去面试的时候,和面试官聊了一个小时的并发编程,整个过程已全记录下来。面试的时候小心翼翼,如履薄冰,生怕说错一句话,就错失机会,担心,面试紧张、卡壳。不知道大家有没有这个问题?​_面试官:_你知道CAS吗,能跟我讲讲吗?_我:_CAS(Compare And Swap),比较并交换。整个AQS

教你怎么用 python 自动整理文件 - 编程思维

我以前经常把下载的东西放在桌面或者“下载”文件夹中,使用完后再也没管它,久而久之便变得乱七八糟,再整理的时候非常痛苦,巴不得有一个自动化的工具帮我归类文档。不知道你是不是有过跟我一样糟糕的体验,不过,前段时间我用Python做了一个根据后缀名整理文件的工具,先来看看效果:自动整理前:自动整理后:效果非常好,舒服多了如果

使用python发送邮件,在自己程序出错时发邮件通知自己. - 编程思维

在工作中,如果自己部署了一些脚本在服务器上,那么就需要在脚本报错时提供一个主动通知.可以在自己脚本的异常处理中, 调用以下代码的发送邮件方法,在触发异常时发送邮件给自己.很多公司开发环境都是内部局域网,这个时候只需要把 smtpserver 换成自己公司内网邮件服务器的ip即可代码: #coding: utf-8

【python 1-16】python手把手教程之——类class的继承、父类、子类 - 编程思维

作者 | 弗拉德来源 | 弗拉德(公众号:fulade_me)继承编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的特殊版本,可使用 继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类, 而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。子类

超简单 python 头像戴圣诞帽教程 - 编程思维

还记得疫情之初,我们用Python给头像戴口罩的文章吗? 开工第一天,先用Python戴个口罩当时只是简单的调用了第三方模块将口罩图片替换入原图,内容非常简短。今天,将为大家提供一个能够通过以下三种方式给头像戴上圣诞帽的Python教程:1.实时打开摄像头读取头像图佩戴圣诞帽2.从本地读取一幅头像图佩戴圣诞帽3.从文

python 绘制属于你的世界地图 - 编程思维

Python之所以这么流行,是因为它不仅能够应用于科技领域,还能用来做许多其他学科的研究工具,绘制地图便是其功能之一。今天我们用matplot工具包之一的 mpl\_toolkits 来绘制世界地图,这是一个简单的可视化工具,如果希望绘制更加复杂的地图,可以考虑使用Google Maps API,不过这不在我们今天的讨

利用股市找到那些存在问题的上市企业 - 编程思维

当某个股票保持下跌的时候,你可以肯定该股票一定有什么地方不对,要么是它的市场,要么是它的公司。——利弗莫尔因此结合自己最近的研究,提出了这个比较新颖的想法:利用股票市场找到已有或潜在食品安全问题的企业。为什么会有这个想法呢?我们知道食品安全事故发生的时间点和媒体报道的时间点之间实际上是有一个间隔的,然而相关利益人士、内