DICOM-SCP,可以直接使用的SCP(.net framework 4.5)控制台接收端
此程序引用的是Dicom.Core 4.0.8.0,也是最后一版支持部署在.net framework 4.5 或以下环境的。如需要部署在.net4.6.1以上的需要查看另一个文档。
1 using Dicom;
2 using Dicom.Log;
3 using Dicom.Network;
4 using Microsoft.Build.Framework;
5 using System;
6 using System.Collections.Generic;
7 using System.Configuration;
8 using System.IO;
9 using System.Linq;
10 using System.Text;
11 using System.Threading.Tasks;
12
13 namespace Store_SCP
14 {
15 class Program
16 {
17 private static readonly string _storagePath = ConfigurationManager.AppSettings["StoragePath"];
18
19 private static readonly int _port = int.Parse(ConfigurationManager.AppSettings["Port"]);
20
21 private static readonly string _calledAE = ConfigurationManager.AppSettings["CalledAE"];
22
23 private static void Main(string[] args)
24 {
25 // preload dictionary to prevent timeouts
26 var dict = DicomDictionary.Default;
27
28 // start DICOM server on port from command line argument or 11112
29 var port = _port;
30 Console.WriteLine($"正在端口上启动C-Store SCP服务器,端口:{port},LocalAE:{_calledAE}");
31
32 using (var server = DicomServer.Create<CStoreSCP>(port))
33 {
34 // end process
35 Console.WriteLine("Press <return> to end...");
36 Console.ReadLine();
37 }
38 }
39
40
41 private class CStoreSCP : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
42 {
43 private static readonly DicomTransferSyntax[] AcceptedTransferSyntaxes = new DicomTransferSyntax[]
44 {
45 DicomTransferSyntax.ExplicitVRLittleEndian,
46 DicomTransferSyntax.ExplicitVRBigEndian,
47 DicomTransferSyntax.ImplicitVRLittleEndian
48 };
49
50 private static readonly DicomTransferSyntax[] AcceptedImageTransferSyntaxes = new DicomTransferSyntax[]
51 {
52 // Lossless
53 DicomTransferSyntax.JPEGLSLossless,
54 DicomTransferSyntax.JPEG2000Lossless,
55 DicomTransferSyntax.JPEGProcess14SV1,
56 DicomTransferSyntax.JPEGProcess14,
57 DicomTransferSyntax.RLELossless,
58 // Lossy
59 DicomTransferSyntax.JPEGLSNearLossless,
60 DicomTransferSyntax.JPEG2000Lossy,
61 DicomTransferSyntax.JPEGProcess1,
62 DicomTransferSyntax.JPEGProcess2_4,
63 // Uncompressed
64 DicomTransferSyntax.ExplicitVRLittleEndian,
65 DicomTransferSyntax.ExplicitVRBigEndian,
66 DicomTransferSyntax.ImplicitVRLittleEndian
67 };
68
69 public CStoreSCP(INetworkStream stream, Encoding fallbackEncoding, Logger log)
70 : base(stream, fallbackEncoding, log)
71 {
72 }
73
74 public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
75 {
76 if (association.CalledAE != _calledAE)
77 {
78 return SendAssociationRejectAsync(
79 DicomRejectResult.Permanent,
80 DicomRejectSource.ServiceUser,
81 DicomRejectReason.CalledAENotRecognized);
82 }
83
84 foreach (var pc in association.PresentationContexts)
85 {
86 if (pc.AbstractSyntax == DicomUID.Verification) pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
87 else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None) pc.AcceptTransferSyntaxes(AcceptedImageTransferSyntaxes);
88 }
89
90 return SendAssociationAcceptAsync(association);
91 }
92
93 public Task OnReceiveAssociationReleaseRequestAsync()
94 {
95 return SendAssociationReleaseResponseAsync();
96 }
97
98 public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
99 {
100 }
101
102 public void OnConnectionClosed(Exception exception)
103 {
104 }
105
106 public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
107 {
108 try
109 {
110 var studyUid = request.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID);
111 var instUid = request.SOPInstanceUID.UID;
112
113 var path = Path.GetFullPath(_storagePath);
114 path = Path.Combine(path, studyUid);
115
116 if (!Directory.Exists(path)) Directory.CreateDirectory(path);
117
118 path = Path.Combine(path, instUid) + ".dcm";
119
120 request.File.Save(path);
121
122 LoggerHelper.Instance().Info($"已成功将文件存入到{path}");
123 }
124 catch (Exception ex)
125 {
126
127 LoggerHelper.Instance().Info($"文件保存失败,失败原因:{ex.Message}");
128 }
129 return new DicomCStoreResponse(request, DicomStatus.Success);
130 }
131
132 public void OnCStoreRequestException(string tempFileName, Exception e)
133 {
134 // let library handle logging and error response
135 }
136
137 public DicomCEchoResponse OnCEchoRequest(DicomCEchoRequest request)
138 {
139 return new DicomCEchoResponse(request, DicomStatus.Success);
140 }
141 }
142 }
143
144 }
using System;
using System.Reflection;
using log4net;
using log4net.Config; namespace Store_SCP
{
public class LoggerHelper
{
private static LoggerHelper _instance = null;
private static object _locker = new object();
private ILog _logger; private LoggerHelper()
{
XmlConfigurator.Configure();
Type type =MethodBase.GetCurrentMethod().DeclaringType;
this._logger = LogManager.GetLogger(type);
} public static LoggerHelper Instance()
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null)
{
_instance = new LoggerHelper();
}
}
}
return _instance;
} public void Debug(object obj)
{
this._logger.Debug(obj);
} public void Error(object obj)
{
this._logger.Error(obj);
} public void Fatal(object obj)
{
this._logger.Fatal(obj);
} public void Info(object obj)
{
this._logger.Info(obj);
} public void Warn(object obj)
{
this._logger.Warn(obj);
} public void Debug(object obj, Exception e)
{
this._logger.Debug(obj, e);
} public void Error(object obj, Exception e)
{
this._logger.Error(obj, e);
} public void Fatal(object obj, Exception e)
{
this._logger.Fatal(obj, e);
} public void Info(object obj, Exception e)
{
this._logger.Info(obj, e);
} public void Warn(object obj, Exception e)
{
this._logger.Warn(obj, e);
} }
}
此是app.config文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
<file value="Logs/" />
<appendToFile value="true" />
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date"/>
<!--这是按日期产生文件夹-->
<datePattern value="yyyyMM\\yyyyMMdd'.txt'"/>
<!--是否只写到一个文件中-->
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<root>
<appender-ref ref="RollingFileAppender" />
<level value="DEBUG" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="StoragePath" value="MYDICOM/"/>
<add key="Port" value="11112"/>
<add key="CalledAE" value="STORESCP11112"/>
</appSettings>
</configuration>
DICOM-SCP,可以直接使用的SCP(.net framework 4.5)控制台接收端的更多相关文章
- scp命令报错-bash: scp: command not found
# scp -bash: scp: command not found # which scp /usr/bin/scp # rpm -qf /usr/bin/scp openssh-clients- ...
- dicom 影像通信(scu、scp)的c-echo、c-store、c-find、c-move
本文主要描述,dicom通信的scu,scp的c-echo.c-store.c-find.c-move的使用. DicomServiceIDicomServiceProviderIDicomCStor ...
- scp 基本用法(提高scp传输速度)
Outline spc 可以帮你实现: Linux Server 之间互传数据: Linux Server 和 Windows Server 之间互传数据: 参考: https://www.cnblo ...
- scp报错 -bash: scp: command not found
环境:RHEL6.5 使用scp命令报错: [root@oradb23 media]# scp /etc/hosts oradb24:/etc/ -bash: scp: command not fou ...
- linux之cp/scp命令+scp命令详解
名称:cp 使用权限:所有使用者 使用方式: cp [options] source dest cp [options] source... directory 说明:将一个档案拷贝至另一档案,或将数 ...
- Linux学习之三--scp命令
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...
- scp 上传文件到多个服务器节点
参考:scp批量上传文件到多台机器上(升级版) 实测,代码可运行. 1.如果遇到syntax error near unexpected token问题,基本是由于windows环境下编写的shell ...
- scp命令详解
\ svn 删除所有的 .svn文件 find . -name .svn -type d -exec rm -fr {} \; linux之cp/scp命令+scp命令详解 名称:cp 使用权限: ...
- linux命令-cp/scp {拷贝}
一 命令解释 名称:cp 使用权限:所有使用者 使用方式: cp [options] source dest cp [options] source... directory 命令参数: -a 尽可能 ...
- scp详解
scp 命令 ================== scp 可以在 2个 linux 主机间复制文件: 命令基本格式: scp [可选参数] file_source file_targe ...
随机推荐
- 第三篇:低功耗模组Air724UG硬件设计手册
今天我们分享最后一篇. 3.20 省电功能 根据系统需求,有两种方式可以使模块进入到低功耗的状态.对于AT版本使用"AT+CFUN"命令可以使模块 进入最少功能状态. 具体的功 ...
- Linux中find命令详解
find命令 find 命令用于查找文件或目录 语法格式: find ./ -type f -name '文件名' 参数依次是:find命令,这里的./指的是当前路径,-type是选择文件类型,文件类 ...
- Docker registry cli 私有仓库镜像查询、删除、上传、下载 shell
#Docker官方私有仓库registry#官方只提供了API接口,不方便使用,就写了个shell#docker-registry安装配置http://www.cnblogs.com/elvi/p/8 ...
- 使用 LLVM 框架创建一个工作编译器,第 1 部分
使用 LLVM 及其中间表示构建一个自定义编译器 LLVM 编译器基础架构提供了一种强大的方法来优化您使用任何编程语言编写的应用程序.了解本系列文章(由两部分组成)第一部分中有关 LLVM 的基础知识 ...
- PySAGES实记
技术背景 PySAGES是一款可以使用GPU加速的增强采样插件,它可以直接对接到OpenMM上进行增强采样分子动力学模拟,这里我们测试一下相关的安装,并尝试跑一个简单的增强采样示例. 安装PySAGE ...
- 轻量数据库管理工具之adminer
github: https://github.com/vrana/adminer 官方文档:https://www.adminer.org/#download Supports: MySQL, Mar ...
- Kafka 1.1.1 源码编译
下载源码 git clone -b 1.1.1 https://github.com/apache/kafka.git --depth=1 使用这样的方式下载主要是解决两个问题:其一,下载指定分支 ...
- VUE3 使用资源路径加载
1.使用场景 有些情况下,我需要使用组件路径动态的方式加载组件. 2.实现方法 import { defineAsyncComponent } from 'vue'; /** * 根据view组件路径 ...
- 使用七牛云上传文件报错incorrect region, please use up-z1.qiniup.com-迷恋自留地
最近用Git提交代码时,一直报如标题所示的错误.百度了很多都无法解决,包括改更改配置,SSh等.最后在一个论坛上,说可能之前输入的账号或密码有误.尝试后,完美解决. 解决方法: 找到如下图的位置: 可 ...
- Kettle用查出来的数据自动创建表
Kettle在表输入的时候,写好很复杂的SQL,有种场景,就是想把这个很复杂的查出来的数据,自动创建一个表. 其实,操作步骤不复杂. 跟着我来做就是了. 1,新建表输出,Shift按住,从表输入拖动 ...