项目背景

    某银行的影像平台由于使用时间长,服务器等配置原因,老影像系统满足不了现在日益增长的数据量的需求,所以急需要升级改造。传统的影像平台使用的是Oracle数据库和简单的架构来存储数据(视频、图片等),所以很难满足现在的业务需求,其中最主要的就是存储下载等速度的影响,综合考虑之后,我们给出了升级改造方案,基于Http协议的数据传输和基于TCP协议的数据传输,按照要求需要用TCP协议,我们最终采用的是Socket网络传输的方案。

TCP协议介绍

  TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,TCP层位于IP层之上,应用层之下的中间层,不同主机的应用层之间经常需要可靠的、像管道一样的连接,但IP层不需要提供这样的机制,而是提供不可靠的包交换。当应用层向TCP层发送用于网间传输的、用8位字节标示的数据流,TCP会把数据流分割为适当长度的报文段,之后TCP把数据包传给IP层,由它来通过网络将包传输给接收端的实体TCP层。TCP是因特网中的传输层协议,使用3次握手协议建立连接。

Socket

TCP通信是严格区分客户端与服务端的,在通信时,必须先由客户端去连接服务器才能实现通信,服务器端不可以主动连接客户端,并且服务器要事先启动,等待客户端的连接。

在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器,一个是Socket类,用于表示客户端。通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,两者建立连接,开始通信。

下面是我们通过Socket建立的模型,是多线程的,首先看服务端代码:

/**
* socket服务端
* @author 我心自在
*
*/
public class Main {
private static Log logger=null;
//线程池
public static ExecutorService executor =null;
/**
* 静态块,初始化
*/
static{
logger=LogFactory.getLog(SocketMain.class);
//线程池
executor = Executors.newFixedThreadPool(123);
}
/**
* 主程序入口
* @param args
*/
public static void main(String[] args) {
ServerSocket server = null;
Socket socket = null;
PropertiesUtil PropertiesUtil = new PropertiesUtil();
try {
//启动Socket服务端
     server=newServerSocket(23232);
while (true) {
//多线程接收客户端请求
socket = server.accept();
if (socket != null) {
executor.execute(new Controller(socket));
}
}
} catch (IOException e) {
logger.error("Main IO异常:"+e.getMessage(),e);
} finally {
try {
if (server != null) {
server.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
logger.error("Main流关闭异常:"+e.getMessage(),e);
}
}
}
}

下面是业务处理类,支持多线程,主要用来处理业务

public class Controller implements Runnable {
private Socket socket;
private static Log logger=LogFactory.getLog(SocketController.class);
   public SocketController(Socket socket) {
super();
this.socket = socket;
}
  public void run() {
//读取文件流
String requestMethod=null;
Map<String,Object> getMethAndNumMap=null;
Map<String,Object> jsonMap=null;
BufferedInputStream bis =null;
OutputStream ops = null;
BufferedWriter bw = null;
BufferedOutputStream bos = null;
Document doc=null;
String XMLString=null;
try {
bis= new BufferedInputStream (socket.getInputStream());
//获取输出流
ops = socket.getOutputStream();
bos = new BufferedOutputStream(ops);
bw = new BufferedWriter(new OutputStreamWriter(ops));
byte[] fileinfo=new byte[256];
try {
bis.read(fileinfo);
} catch (IOException e1){
logger.error("流读取异常...."+e1.getMessage(),e1);
}
if(fileinfo!=null){
fileInfoString=new String(fileinfo).trim();
}
jsonMap=JSONUtil.jsonToMap(fileInfoString);
requestMethod=(String) jsonMap.get("requestMethod");
if (!(requestMethod==null||"".equals(requestMethod))) {
switch (requestMethod){
case "login":
Login.login(XMLString,bw,doc);//登录接口
break;
case "XXXX":
XXX.xxx();
break;
default:
//请求方法错误 }
}
} catch (UnknownHostException e) {
logger.error("Socket未知端口:"+e.getMessage(),e);
} catch (IOException e) {
logger.error("Controller读流流异常:"+e.getMessage(),e);
}finally{
try {
if (bw!=null) {
bw.flush();
bw.close();
}
if(ops!=null){
ops.close();
}
if(bos!=null){
bos.close();
}
bis.close();
socket.close();
} catch (IOException e) {
logger.error("socket关闭异常:"+e.getMessage(),e);
}
}
}

  这是一个完整的Socket传输框架,基本思想就是,通过输入流接到客户端发送过来的报文,然后进行解析,为什么统一用字节流接受呢,这里由具体的业务流程决定,因为我们的文件上传分两部分,一部分是文件信息,一部分是文件流,所以为了方便,统一使用字节流接收,根据字节流中的请求接口方法,调用对应的接口方法,完成业务处理。因为客户端的报文有两种,一种是XML类型的报文,另外一种是json格式的报文,这里只贴出了部分json格式的代码。差的只是一个XML的解析,解析方式很多,就不再赘述。

下面是客户端代码,以登录为例:

public class LoginTest {
public static void main(String[] args) {
String xml =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<root>"
+ "<requestMethod>login</requestMethod>"
+ "<userinfo>"
+ "<loginname>test</loginname>"
+ "<passwd>123456</passwd>"
+ "</userinfo>"
+ "</root>";
Socket socket=null;
BufferedWriter bw=null;
BufferedReader br=null;
try {
socket=new Socket(”10.182.1.100“, 23232);
bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(xml);
bw.newLine();
bw.flush();
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("服务器返回报文:"+br.readLine());
bw.close();
br.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

  客户端代码非常简单,基本就是以流的形式发送报文,发送到客户端,完成请求,收到服务器响应后,关闭连接,完成一次请求。

  以上只是一个简单的Socket通信模型,可以应用到很多不同的项目。大致思路就是通过Socket通信,获取客户端发送过来的报文,然后对报文进行解析,根据请求方法,调用不同的业务接口,处理不同的业务,结合不同的场景,执行不同的操作。

基于TCP协议的项目架构之Socket流传输的实现的更多相关文章

  1. 网络编程(二)--TCP协议、基于tcp协议的套接字socket

    一.TCP协议(Transmission Control Protocol 传输控制协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会 ...

  2. 网络编程(二)——TCP协议、基于tcp协议的套接字socket

    TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...

  3. JAVA 基于TCP协议的一对一,一对多文件传输实现

    最近老师给我们上了多线程和TCP和UDP协议,其中一个要求就是我们用JAVA协议一个基于TCP和UDP这两种协议的一对一文件上传和一对多文件上传. 然后我就开始分析TCP和UDP这两个协议的特点,发现 ...

  4. 基于Tcp协议的简单Socket通信实例(JAVA)

    好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些网络编程的基础,这里就不提了,只记录最简单易懂实用的东西. ...

  5. (2)socket的基础使用(基于TCP协议)

    socket()模块函数用法 基于TCP协议的套接字程序 netstart -an | findstr 8080 #查看所有TCP和UDP协议的状态,用findstr进行过滤监听8080端口 服务端套 ...

  6. 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现

    一.客户端/服务器架构(C/S架构)                                                即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...

  7. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  8. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  9. 基于TCP协议的socket套接字编程

    目录 一.什么是Scoket 二.套接字发展史及分类 2.1 基于文件类型的套接字家族 2.2 基于网络类型的套接字家族 三.套接字工作流程 3.1 服务端套接字函数 3.2 客户端套接字函数 3.3 ...

随机推荐

  1. LDA主题模型学习笔记5:C源代码理解

    1.说明 本文对LDA原始论文的作者所提供的C代码中LDA的主要逻辑部分做凝视,原代码可在这里下载到:https://github.com/Blei-Lab/lda-c 这份代码实现论文<Lat ...

  2. vue-购物车

    最终的实现效果: 需求分析: 购物车需要展示一个已加入购物车的商品列表,包含商品名称,商品单价,购买数量和操作等信息,还需要实时显示购买的总价.其中购买数量可以增加或减少,每类商品还可以从购物车中移除 ...

  3. nginx+zuul

      最近将公司的一些服务迁移到spring cloud了,感觉zuul智能路由的功能非常好用,比以前手动在nginx中添加localtion,upstream方便多了,但是服务域名的80端口被ngin ...

  4. 比最差的API(ETW)更差的API(LTTng)是如何炼成的, 谈如何写一个好的接口

    最近这几天在帮柠檬看她的APM系统要如何收集.Net运行时的各种事件, 这些事件包括线程开始, JIT执行, GC触发等等. .Net在windows上(NetFramework, CoreCLR)通 ...

  5. 微信小程序——微信支付

    这个讲起来也就比较麻烦一点,因为需要的不仅仅是咱们代码上的技术,嘿嘿! 先整理一下思路.如果想做微信支付: 1.现有一个公司账户(非个人账户),并且实名认证过的. 2.微信号 必须开通微信支付功能. ...

  6. Git使用简单总结

    创建版本库git add加入到暂存区git commit -m" "加入到分支 时光机穿梭git satus查看仓库的当前状态git diff file 查看修改内容 版本回退HE ...

  7. 【二十六】php之文件编程

    1.获取文件的相关信息 fopen.fstat.fclose(打开文件.获取文件相关信息.关闭文件) filesize.filectime.filemtime.fileatime(文件大小.上次cha ...

  8. iOS常见的几种加密方法(base64.MD5.Token传值.系统指纹验证。。加密)

    普通加密方法是讲密码进行加密后保存到用户偏好设置中 钥匙串是以明文形式保存,但是不知道存放的具体位置 一. base64加密 base64 编码是现代密码学的基础 基本原理: 原本是 8个bit 一组 ...

  9. iOS开发--SQLite重要框架FMDB的使用

    什么是FMDB: FMDB是一个和iOS的SQLite数据库操作相关的第三方框架.主要把C语言操作数据库的代码用OC进行了封装.使用者只需调用该框架的API就能用来创建并连接数据库,创建表,查询等. ...

  10. Python学习日记day3:数据类型

    1.数据类型int :如1.2.4等, 用于计算 bool: True , False ,用户判断 str: 储存少量数据,进行操作.如:'fdasklfjfladfl','而而噩噩','1234' ...