项目背景

    某银行的影像平台由于使用时间长,服务器等配置原因,老影像系统满足不了现在日益增长的数据量的需求,所以急需要升级改造。传统的影像平台使用的是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. java.util.ConcurrentModificationException 异常问题详解

    环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修改就会出现java.util.ConcurrentModificationException异常, ...

  2. Python 学习(1) 简单的小爬虫

    最近抽空学了两天的Python,基础知识都看完了,正好想申请个联通日租卡,就花了2小时写了个小爬虫,爬一下联通日租卡的申请页面,看有没有好记一点的手机号~   人工挑眼都挑花了. 用的IDE是PyCh ...

  3. C++、Objective-C 混合编程

    在XCODE中想使用C++代码,你须要把文件的扩展名从.m改成.mm.这样才会启动g++编译器. 我们来看个測试代码: [java] view plaincopy class TestC { priv ...

  4. vim 命令整理(自己经常使用)

    vimm(vimsual)是Linux/UNIX系列OS中通用的全屏编辑器. vimm分为两种状态,即命令状态和编辑状态.在命令状态下.所键入的字符系统均作命令来处理.如:q代表退出,而编辑状态则是用 ...

  5. 【分享】iTOP4412开发板-Bluetooth移植文档

    [分享]iTOP4412开发板-Bluetooth移植文档 最近须要把Bluetooth移植到iTOP-4412 开发平台.查阅了相关资料,经过一段时间的研究.调试,最终成功的将蓝牙功能移植到了开发板 ...

  6. 基于Handler架构的录音程序

    近期我的app须要一个录音功能,于是搜到这篇文章 文章中录音线程与主线程间的通讯是通过内部类訪问外部类成员变量的方式来实现 while (isRecord == true) { //isRecord是 ...

  7. 掀起Azure AD的盖头来——深入理解Microsoft Graph应用程序和服务权限声明

    作者:陈希章 发表于 2017年7月12日 引子 这是一篇计划外的文章.我们都知道要进行Microsoft Graph的开发的话,需要进行应用程序注册.这个在此前我已经有专门的文章写过了.但这里存在一 ...

  8. ABP入门系列(9)——权限管理

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 完成了简单的增删改查和分页功能,是不是觉得少了点什么? 是的,少了权限管理.既然涉及到了权限,那我 ...

  9. 码农的奋斗之路 CTO说 读后感

    拜读了各位大神的分享,对CTO的职责有了进一步的认识. 什么是CTO? CTO需要具备哪些技能? CTO与管理 CTO的作用是什么? 如何体现CTO的价值? CTO撸不撸代码? 小结

  10. 前端开发JavaScript清除浏览器缓存的方法

    查看和删除浏览器缓存的方法=====>打开 最近在开发项目中发现有时候总要频繁地清除浏览器缓存,不然总是显示的过时的信息 浏览器缓存有利有弊,有些数据需要缓存下来使得页面打开更快提高网站性能,但 ...