Socket是什么呢?

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
 UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。

Socket 原理

Socket 连接,至少需要一对套接字,分为 clientSocket,serverSocket 连接分为3个步骤:

(1) 服务器监听:服务器并不定位具体客户端的套接字,而是时刻处于监听状态;

(2) 客户端请求:客户端的套接字要描述它要连接的服务器的套接字,提供地址和端口号,然后向服务器套接字提出连接请求;

(3) 连接确认:当服务器套接字收到客户端套接字发来的请求后,就响应客户端套接字的请求,并建立一个新的线程,把服务器端的套接字的描述发给客户端。一旦客户端确认了此描述,就正式建立连接。而服务器套接字继续处于监听状态,继续接收其他客户端套接字的连接请求.

过程图解:

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。

在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。

客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

实例展示:

服务器端:

package com.socket.test;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket; public class SocketServer {
public static void main(String[] args) throws Exception {
// 监听指定的端口
int port = 55533;
ServerSocket server = new ServerSocket(port); // server将一直等待连接的到来
System.out.println("server将一直等待连接的到来");
Socket socket = server.accept();
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
//只有当客户端关闭它的输出流的时候,服务端才能取得结尾的-1
while ((len = inputStream.read(bytes)) != -1) {
// 注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len, "UTF-8"));
}
System.out.println("get message from client: " + sb);
  // 发送信息给客户端
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello Client,I get the message.".getBytes("UTF-8")); inputStream.close();
outputStream.close();
socket.close();
server.close();
}
}

当读取完客户端的消息后,打开输出流,将指定消息发送回客户端

客户端:

package com.socket.test

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket; public class SocketClient {
public static void main(String args[]) throws Exception {
// 要连接的服务端IP地址和端口
String host = "127.0.0.1";
int port = 55533;
// 与服务端建立连接
Socket socket = new Socket(host, port);
// 建立连接后获得输出流
OutputStream outputStream = socket.getOutputStream();
String message = "你好 fuwuqiduan";
socket.getOutputStream().write(message.getBytes("UTF-8"));
//通过shutdownOutput高速服务器已经发送完数据,后续只能接受数据
socket.shutdownOutput(); InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1) {
//注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len,"UTF-8"));
}
System.out.println("get message from server: " + sb); inputStream.close();
outputStream.close();
socket.close();
}
}

客户端也有相应的变化,在发送完消息时,调用关闭输出流方法,然后打开输出流,等候服务端的消息。

服务器段优化

在上面的例子中,服务端仅仅只是接受了一个Socket请求,并处理了它,然后就结束了,但是在实际开发中,一个Socket服务往往需要服务大量的Socket请求,那么就不能再服务完一个Socket的时候就关闭了,这时候可以采用循环接受请求并处理的逻辑:

package com.socket.test
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket; public class SocketServer {
public static void main(String args[]) throws IOException {
// 监听指定的端口
int port = 55533;
ServerSocket server = new ServerSocket(port);
// server将一直等待连接的到来
System.out.println("server将一直等待连接的到来"); while(true){
Socket socket = server.accept();
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1) {
// 注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len, "UTF-8"));
}
System.out.println("get message from client: " + sb);
inputStream.close();
socket.close();
} }
}

这种一般也是新手写法,但是能够循环处理多个Socket请求,不过当一个请求的处理比较耗时的时候,后面的请求将被阻塞,所以一般都是用多线程的方式来处理Socket,即每有一个Socket请求的时候,就创建一个线程来处理它。

  不过在实际生产中,创建的线程会交给线程池来处理,为了:

  • 线程复用,创建线程耗时,回收线程慢
  • 防止短时间内高并发,指定线程池大小,超过数量将等待,方式短时间创建大量线程导致资源耗尽,服务挂掉
package com.socket.test

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class SocketServer {
public static void main(String args[]) throws Exception {
// 监听指定的端口
int port = 55533;
ServerSocket server = new ServerSocket(port);
// server将一直等待连接的到来
System.out.println("server将一直等待连接的到来"); //如果使用多线程,那就需要线程池,防止并发过高时创建过多线程耗尽资源
ExecutorService threadPool = Executors.newFixedThreadPool(100); while (true) {
Socket socket = server.accept(); Runnable runnable=()->{
try {
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1) {
// 注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len, "UTF-8"));
}
System.out.println("get message from client: " + sb);
inputStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
};
threadPool.submit(runnable);
} }
}

借鉴网址:https://www.cnblogs.com/yiwangzhibujian/p/7107785.html

Socket通信,基本方法介绍的更多相关文章

  1. python 全栈开发,Day36(作业讲解(大文件下载以及进度条展示),socket的更多方法介绍,验证客户端链接的合法性hmac,socketserver)

     先来回顾一下昨天的内容 黏包现象粘包现象的成因 : tcp协议的特点 面向流的 为了保证可靠传输 所以有很多优化的机制 无边界 所有在连接建立的基础上传递的数据之间没有界限 收发消息很有可能不完全相 ...

  2. .NET开源高性能Socket通信中间件Helios介绍及演示

    一:Helios是什么 Helios是一套高性能的Socket通信中间件,使用C#编写.Helios的开发受到Netty的启发,使用非阻塞的事件驱动模型架构来实现高并发高吞吐量.Helios为我们大大 ...

  3. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  4. 2017年8月9日学习内容存放 #socket通信介绍

    2017年8月9日学习内容存放 #socket通信介绍 ''' OSI七层 应用 表示 会话 传输 网络 ip 数据链路 mac 物理层 网线 http smtp dns ftp ssh snmp i ...

  5. libevent 实现的socket 通信 server以及解决找不到动态库的方法

    注: client 个人觉得没必要用 libvent来实现就没写 注:由于 涉及到回调函数的使用 如有疑惑的可以先去了解回调函数的实现机理 先来说一下 libevent主要是干啥的 : 内部封装了 s ...

  6. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  7. C#socket通信-----多线程

    我在之前的socket通信的基础上做了一点改进,使用多线程来使用,程序更加简洁实用.不足之处请指教哦! 话不多说,之前的随笔也有介绍,直接上代码啦! 服务端socket(serverSocket): ...

  8. Android开发--Socket通信

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时 ...

  9. .net平台下C#socket通信(上)

    在开始介绍socket前先补充补充基础知识,在此基础上理解网络通信才会顺理成章,当然有基础的可以跳过去了.都是废话,进入正题. TCP/IP:Transmission Control Protocol ...

  10. .net平台下C#socket通信(中)

    上篇.net平台下C#socket通信(上)介绍了socket通信的基本原理及最基本的通信方式.本文在此基础上就socket通信时经常遇到的问题做一个简单总结,都是项目中的一些小问题,拿来此处便于下次 ...

随机推荐

  1. Package Control:There are no packages available for installation

    百度推荐的sublime3,里面好多全家桶,注意安装. 我的问题报错是:Package Control:There are no packages available for installation ...

  2. javaScript的三种储存方式

    (一).SessionStorage     会话储存 (二).localStorage           本地储存 (三).Cookier                   现实中为:饼干    ...

  3. .Net: C#中的委托(Delegate)和事件(Event)

    委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真 是太容易了,而没有过去的人每次 ...

  4. Centos7上设置zookeeper自启动

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/zhouzhiwengang/artic ...

  5. Flutter —快速开发的IDE快捷方式

    老孟导读:这是老孟翻译的精品文章,文章所有权归原作者所有. 欢迎加入老孟Flutter交流群,每周翻译2-3篇付费文章,精彩不容错过. 原文地址:https://medium.com/flutter- ...

  6. 作为架构师必须知道的Netty原理和使用

    本文首发于微信公众号[猿灯塔],转载引用请说明出处 今天呢!灯塔君跟大家讲: Netty应用 一.Netty简介 1.Netty下载 官网:https://netty.io/downloads.htm ...

  7. 一、web自动化快速使用

        1.什么是Selenium? selenium是一款基于web网页的UI自动化测试的框架,用来做web自动化测试 支持多浏览器操作,ie.firefox.chrome.edge.safaria ...

  8. css3动画讲解,关于css3的@keyframes和animation

    通过css3我们可以创建动画,它能取代gif图片.Flash.Js动画等,css3的animation动画是应用在html的DOM元素上的,通过样式来实现的. @keyframes 规则 @Keyfr ...

  9. 富文本编辑器实现从word中复制图片(外挂)

    1问题 基于web的富文本编辑器的功能普遍较弱,而word是公认的宇宙第一好用的文档编辑器,所以许多人都习惯先在word中编辑,然后再将内容粘到web富文本编辑器中. 但是,这种操作有一个问题:图片带 ...

  10. 状压DP之愤怒的小鸟

    题目 传送们P2831 题目较长,不加以赘述 直接步入正题 首先是数学知识,我们可以先根据给出的任意两只猪构建相应的抛物线,同时再构建完之后应判断抛物线的合法性(比如a小于0啊,等等),公式推演就不在 ...