`

socket编程学习笔记

阅读更多

       聊到socket编程,我脑子第一反应就是activeMq、及JMS的其他应用底层都是基于socket实现的,当然我们日常用的QQ、微信等通讯工具也是基于socket实现的(其实我们工作中常用到的log4j底层也用到了socket),由于socket应用面如此广泛、所以我今天翻阅了大量网上资料、并自己写了简单的例子进行学习,下面聊聊我的学习笔记和心得。

       当然在今天学习之前我就有使用过socket进行项目编码的经验了,记得当初在给某一线城市房管局做项目时,档案馆的档案都是基于PDA服务器进行存管的,PDA对外提供了socket服务,所以当初我就用的socket客户端代码去调用PDA服务发起调档的请求。

 

       下面是我11年写的代码,现在贴出来,因为当时档案馆库房很多,每个库房都有socket服务器,所以代码需要通过判断很多规则动态调用不同库房的socket服务器、并与之通讯,发送调档请求。

public boolean socketSendMessage2PDA(String daidUnionStr, int type) {
    log.info("调档发送时给PDA发送调档信息,发送的档案ID字符串为:" + daidUnionStr);
    if (daidUnionStr != null) {
        String[] daidList = daidUnionStr.split(":");
        for (String daid : daidList) {
            TpaDast tpaDast = (TpaDast) this.findEntityById("TpaDast", Long.valueOf(daid));
TpaDawzxx dawzxx = tpaDast.getDawzxx();
List<TpaDaglxxb> glxxbList = this.getDaglxxbListByDabh(tpaDast.getDacode());
            if (dawzxx != null) {
                ConfigService configService = (ConfigService) Framework.getEngine().getContainer().getComponent("configService");
String hostIP = "", cqrxm = "未知";
StringBuffer addressSbf = new StringBuffer();
                if (glxxbList != null && glxxbList.size() > 0) cqrxm = glxxbList.get(0).getCqrxm();
//根据config.properties文件中配置的档案的PDA服务地址
                //1号库房PDA服务器地址
if (dawzxx.getFh() == 1l || dawzxx.getFh().equals(1l)) hostIP = configService.getString("server1_Ip");
//2号库房PDA服务器地址
if (dawzxx.getFh() == 2l || dawzxx.getFh().equals(2l)) hostIP = configService.getString("server2_Ip");
//3号库房PDA服务器地址
if (dawzxx.getFh() == 3l || dawzxx.getFh().equals(3l)) hostIP = configService.getString("server3_Ip");
//4号库房PDA服务器地址
if (dawzxx.getFh() == 4l || dawzxx.getFh().equals(4l)) hostIP = configService.getString("server4_Ip");
//5号库房PDA服务器地址
if (dawzxx.getFh() == 5l || dawzxx.getFh().equals(5l)) hostIP = configService.getString("server5_Ip");
log.info("调用PDA服务器的IP地址为:" + hostIP);
//动态拼接PDA能够识别的位置信息
if (dawzxx.getFh() < 10) addressSbf.append("0").append(dawzxx.getFh());
                else addressSbf.append(dawzxx.getFh());
addressSbf.append(dawzxx.getQh());
                if (dawzxx.getLh() < 10) addressSbf.append("0").append(dawzxx.getLh());
                else addressSbf.append(dawzxx.getLh());
                if (dawzxx.getMh() == 1 || dawzxx.equals(1)) addressSbf.append("L");
                else if (dawzxx.getMh() == 2 || dawzxx.equals(2l)) addressSbf.append("R");
                if (dawzxx.getJh() < 10) addressSbf.append("0").append(dawzxx.getJh());
                else addressSbf.append(dawzxx.getJh());
                if (dawzxx.getGh() < 10) addressSbf.append("0").append(dawzxx.getGh());
                else addressSbf.append(dawzxx.getGh());
log.info("动态PDA库房地址为:" + addressSbf.toString());
                try {
                    //Socket发送给PDA服务器代码
Socket socket = new Socket();//需要动态根据位置发送服务
SocketAddress socketAddress = new InetSocketAddress(hostIP, 1001);
socket.connect(socketAddress, 3000);//连接三秒钟超时设置
OutputStream outputStream = socket.getOutputStream();
StringBuffer sbf = new StringBuffer();
sbf.append("<?xml version='1.0' encoding='gb2312'?>");
sbf.append("<XMLPackage>");
sbf.append("<Command CmdType='2'/>");
sbf.append("<data>");
sbf.append("<row Code='" + tpaDast.getDacode() + "' Name='" + cqrxm + "' Address='" + addressSbf.toString() + "' Archives_id='" + tpaDast.getId() + "' State='" + type + "'/>"); //还档state变成2,其它都是一样
sbf.append("</data>");
sbf.append("</XMLPackage>");
log.info("发送" + tpaDast.getDacode() + "信息为:\n" + sbf.toString());
outputStream.write(sbf.toString().getBytes());
log.info("Socket主机端连接信息为:\n" + socket);
InputStream is = socket.getInputStream();
                    byte[] bytes = new byte[1024];
                    int n = is.read(bytes);
log.info(tpaDast.getDacode() + "发送给PDA系统,回调信息为:\n" + new String(bytes, 0, n));
outputStream.flush();
outputStream.close();
is.close();
} catch (Exception e) {
                    log.info("调档发送PDA服务信息错误,调档失败,原因是PDA服务器没有开启!具体信息如下:\n" + e.getMessage());
                    return false;
}
            }
        }
    }
    return true;
}

 

 

时至今日我又翻阅了相关资料系统的进行了学习,情况总结如下:

 

概念:

Socket是一组编程接口(API), 是对TCP/IP协议的封装和应用。介于传输层和应用层,大致驻留在 OSI 模型的会话层,向应用层提供统一的编程接口。应用层不必了解TCP/IP协议细节。直接通过对Socket接口函数的调用完成数据在IP网络的传输。

 

分类:

基于传输层差异,可以将Socket分为4种类型:
    (1)基于TCP的Socket:提供给应用层可靠的流式数据服务,使用TCP的Socket应用程序协议:BGP,HTTP,FTP,TELNET等。优点:基于数据传输的可靠性。
   (2)基于UDP的Socket:适用于数据传输可靠性要求不高的场合。基于UDP的Socket应用程序或协议有:RIP,SNMP,L2TP等。
  (3)基于RawIp的Socket:非连接,不可靠的数据传输。特点:能使应用程序直接访问网络层。基于RawIp的Socket有ping ,tracert,ospf等。
  (4)基于链路层的Socket。为IS-IS协议提供的Socket接口。使IS-IS协议可通过Socket直接访问链路层。非连接,不可靠通信服务。

 

实践:

我主要是针对socket实现方式TPC/ID和UPD的两种实现方式进行了学习,先来看看他们的通讯方式链接过程图(图片来源于网络):

TCP/IP链接过程



 UPD链接过程:



 对比两者区别:

TCP:Transimission Control Protocol传输控制协议。

UPD:User Datagram Protocol用户数据包协议。

两者都属于OSI模型中的第四层——传输层的协议。

两者相比:

TCP协议面向连接,UDP协议面向非连接;(链接)

TCP协议传输速度慢,UDP协议传输速度快;(速度)

TCP有丢包重传机制,UDP没有;(重传)

TCP协议保证数据正确性,UDP协议可能丢包;(正确性)

TCP适合传递大量数据,UPD适合传递少量数据。(数据量)

 

说了基本概念后,我用代码编写了主机、客户端进行socket通讯的代码,代码如下:

服务端代码socketServer.java类:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
 * Created by 峰 on 2017/4/6.
 * 服务器类
 */
public class socketServer {
    private int port = 8189;// 默认服务器端口
public socketServer() {
    }
    // 创建指定端口的服务器
public socketServer(int port) {
        this.port = port;
}

    // 提供服务
public void service() {
        try {// 建立服务器连接
ServerSocket server = new ServerSocket(port);
// 等待客户连接
Socket socket = server.accept();
            try {
                // 读取客户端传过来信息的DataInputStream
DataInputStream in = new DataInputStream(socket
                        .getInputStream());
// 向客户端发送信息的DataOutputStream
DataOutputStream out = new DataOutputStream(socket
                        .getOutputStream());
// 获取控制台输入的Scanner
Scanner scanner = new Scanner(System.in);
                while (true) {
                    // 读取来自客户端的信息
String accpet = in.readUTF();
System.out.println(accpet);
String send = scanner.nextLine();
System.out.println("服务器:" + send);
// 把服务器端的输入发给客户端
out.writeUTF("服务器:" + send);
}
            } finally {// 建立连接失败的话不会执行socket.close();
socket.close();
}
        } catch (IOException e) {
            e.printStackTrace();
}
    }

    public static void main(String[] args) {
        new socketServer().service();
}
}

 

客户端代码socketClient.java类:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
/**
 * Created by 峰 on 2017/4/9.
 * 客户端类
 */
public class socketClient {

    private String host = "localhost";// 默认连接到本机
private int port = 8189;// 默认连接到端口8189
public socketClient() {
    }

    // 连接到指定的主机和端口
public socketClient(String host, int port) {
        this.host = host;
        this.port = port;
}

    public void chat() {
        try {
            // 连接到服务器
Socket socket = new Socket(host, port);
            try {
                // 读取服务器端传过来信息的DataInputStream
DataInputStream in = new DataInputStream(socket
                        .getInputStream());
// 向服务器端发送信息的DataOutputStream
DataOutputStream out = new DataOutputStream(socket
                        .getOutputStream());
// 装饰标准输入流,用于从控制台输入
Scanner scanner = new Scanner(System.in);
                while (true) {
                    String send = scanner.nextLine();
System.out.println("客户端:" + send);
// 把从控制台得到的信息传送给服务器
out.writeUTF("客户端:" + send);
// 读取来自服务器的信息
String accpet = in.readUTF();
System.out.println(accpet);
}

            } finally {
                socket.close();
}
        } catch (IOException e) {
            e.printStackTrace();
}
    }

    public static void main(String[] args) {
        new socketClient().chat();
}

}

 

测试结果:

服务端信息截图:

 客户端信息截图:



 

 

通讯原理及过程图解(来源于网络):



 
 

 

附言:因为时间问题、我这里只研究了java.net下的socket,其实还有别的实现方式,比如linux下面也有socket,参考 http://blog.csdn.net/hguisu/article/details/7445768/

现在网络上也有很多很好的socket学习文章,具体可以参考下面链接(当然我也都是看过了的)

http://acm.tzc.edu.cn/acmhome/projectList.do?method=projectNewsDetail&nid=2

http://blog.csdn.net/hguisu/article/details/7445768/

http://www.cnblogs.com/kinghitomi/archive/2012/01/19/2327424.html

  • 大小: 40.2 KB
  • 大小: 27.7 KB
  • 大小: 82.4 KB
  • 大小: 13.6 KB
  • 大小: 13 KB
分享到:
评论

相关推荐

    COMSOL模拟碳酸钙岩石与盐酸反应的随机孔隙酸化路径及布林克曼流动形成的分形结构

    内容概要:本文详细介绍了利用COMSOL软件模拟碳酸钙(CaCO3)在岩石中与盐酸(HCl)反应过程中产生的随机孔隙酸化路径及其形成的布林克曼流动。首先,通过蒙特卡洛方法生成随机孔隙分布,模拟真实岩石内部复杂的孔隙结构。接着,采用布林克曼方程处理多孔介质中的粘性力和渗透流动,并引入化学反应模块,模拟CaCO3与HCl之间的化学反应。随着模拟的进行,酸液流动路径逐渐形成类似雪花状的分形结构,展示了流动与溶解之间的动态博弈。最后,通过自适应网格技术和粒子追踪功能,精确捕捉并可视化这些精美的分形图案。 适合人群:从事地质工程、材料科学、化学工程等领域研究的专业人士,以及对多孔介质传输现象感兴趣的科研工作者。 使用场景及目标:适用于研究多孔介质内的化学反应和流体流动特性,特别是对于优化石油开采中的酸化压裂工艺具有重要指导意义。 其他说明:文中提供了详细的MATLAB和COMSOL代码片段,帮助读者理解和重现模拟过程。此外,强调了随机性和确定性在微观尺度上的相互作用,揭示了自然界深层次的规律。

    基于滑模控制的永磁同步电机直接转矩控制仿真建模与实现

    内容概要:本文详细介绍了将滑模控制(SMC)应用于永磁同步电机(PMSM)直接转矩控制(DTC)的技术细节。首先解释了转矩和磁链误差计算方法,接着探讨了滑模面的设计及其对系统抖振的影响。文中还提供了扇区矢量选择的具体实现方式,并深入讨论了磁链观测器的改进措施。此外,文章分析了滑模控制器的设计要点以及仿真过程中需要注意的关键参数配置。通过对比传统PI控制,验证了滑模控制在提高系统鲁棒性和快速响应方面的优势。 适合人群:从事电机控制系统研究的专业人士,尤其是对永磁同步电机直接转矩控制感兴趣的科研工作者和技术人员。 使用场景及目标:适用于希望深入了解并掌握滑模控制理论及其在PMSM-DTC应用中的具体实现方法的研究人员。目标是在实际项目中能够运用滑模控制提升系统的稳定性和性能。 其他说明:文中提供的MATLAB/Simulink代码片段有助于读者更好地理解和复现实验结果。同时提醒读者关注一些常见的陷阱,如参数选择不当可能导致的问题。

    北京大学网络安全工作人员管理规定:涵盖人员职责、聘用、转岗离岗、教育培训及第三方管理

    内容概要:本文详细介绍了北京大学针对网络安全工作人员的管理规定,旨在加强网络安全管理和明确不同角色的责任。全文分为九章,涵盖了网络安全工作人员及其职责、聘用管理、转岗和离岗管理、教育培训、第三方人员管理及奖惩措施等方面的内容。重点在于明确各级单位和人员的具体职责,确保网络安全制度的有效执行,并强调了对第三方人员的严格管控和保密要求。 适合人群:适用于高校网络安全管理人员及相关技术人员,尤其是北京大学及其下属单位的网络安全工作者。 使用场景及目标:①帮助高校建立健全网络安全管理体系;②指导网络安全工作人员明确自身职责,提高工作效率;③规范第三方人员的访问和操作,降低安全风险。 其他说明:本文还提供了多个附件,如网络安全承诺书、访问申请表和保密协议模板,便于实际操作和管理。

    网络设备市场现状与发展趋势分析(2024-2030年)-技术革新与智能化应用

    内容概要:本文深入探讨了中国网络设备市场的现状及其未来发展潜力。首先介绍了网络设备的基本概念及其作为现代通信网络基础设施的重要地位,随后分析了当前市场面临的挑战和技术进步带来的机遇。文中特别强调了5G、物联网、云计算等新兴技术对网络设备性能和安全性的更高要求,以及由此催生的高带宽、低延迟产品的市场需求。此外,还讨论了软件定义网络(SDN)、网络功能虚拟化(NFV)、边缘计算等新技术的应用前景,指出未来网络设备将更加智能化、自动化,并能更好地支持AI和ML技术。最后,通过对多家领先企业的案例研究,展示了行业内竞争态势及各公司在技术创新方面的努力。 适用人群:从事网络设备相关领域的研究人员、工程师、管理人员,以及关注该领域发展的投资者。 使用场景及目标:帮助读者了解网络设备行业的最新动态和技术趋势,为制定战略决策提供依据;同时为企业和个人投资者提供市场洞察,辅助其做出合理的投资选择。 其他说明:报告基于详实的数据分析和专家意见撰写而成,旨在为专业人士提供有价值的参考资料。

    西门子1200 PLC码垛系统的SCL编程详解:涵盖变频器、机器人、视觉系统集成

    内容概要:本文详细介绍了基于西门子1200 PLC的码垛系统的设计与实现,涵盖了多个关键技术点。首先,文章讲解了Modbus TCP通讯的实现方法,展示了如何通过TSEND_C和TRCV_C功能块进行工业相机和机器人之间的数据传输,并提供了具体的报文处理代码。接着,文章深入探讨了SCL编程的优势及其在复杂逻辑处理中的应用,如托盘堆叠算法,该算法能够根据当前层数动态调整机械手的高度,确保堆叠的安全性和稳定性。此外,文章还介绍了机器人控制中的移位寄存器实现的动作队列管理和变频器的速度平滑处理,以及视觉系统的坐标解析和异常处理机制。最后,文章强调了良好的注释规范和异常处理链的重要性,确保程序的可维护性和可靠性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是熟悉西门子PLC编程和SCL语言的从业者。 使用场景及目标:适用于需要深入了解和掌握西门子1200 PLC在码垛系统中的具体应用的技术人员。目标是帮助读者理解并实现多设备联动的复杂控制系统,提高系统的稳定性和效率。 其他说明:文中提供的代码示例和详细的解释有助于读者更好地理解和应用相关技术,同时也为后续的维护和优化提供了宝贵的参考资料。

    ZYNQ平台PS与PL端驱动程序编写

    适合从入门到进阶的驱动程序爱好者

    计算机二级上机题库答案.pdf

    计算机二级上机题库答案.pdf

    深信服下一代防火墙:构建全方位立体网络安全监测与响应体系

    内容概要:本文介绍了深信服科技推出的下一代防火墙(NGAF)网络安全监测解决方案。随着网络安全成为国家战略的一部分,企业不仅需要遵守法律法规,还需增强自身的网络安全防护能力。传统的安全措施难以应对复杂的新型威胁,如APT攻击。深信服的NGAF通过多维度的安全监测,包括入侵风险、僵尸主机、实时漏洞、数据风险、黑链风险以及对外DoS攻击监测等功能,结合云端威胁情报共享,为企业提供了一套立体化的主动防御体系。该方案不仅可以旁路或串接部署,不影响现有业务系统,还能通过外置数据中心进行日志管理和综合分析,帮助用户快速定位和解决安全问题。 适合人群:IT管理人员、网络安全专家、企业信息安全负责人。 使用场景及目标:适用于各类企业的网络安全建设,特别是需要应对复杂网络攻击的企业。目标是构建一个多层次、全方位、智能化的网络安全监测和响应体系,提高企业的安全防护能力和应急响应速度。 其他说明:深信服NGAF不仅提升了网络安全监测的效果,还降低了运维成本,改变了传统的被动防护模式,使得安全运维更加高效和智能化。

    COMSOL超表面偏振转换技术:介质半波片与1/4波片的设计与仿真

    内容概要:本文详细介绍了利用COMSOL软件进行超表面偏振转换的设计方法,主要聚焦于介质半波片和1/4波片的实现。文中首先解释了超表面的基本原理及其在光学调控中的重要作用,随后具体阐述了如何在COMSOL中设置材料属性、创建几何结构并施加适当的边界条件。针对半波片和1/4波片的不同需求,分别探讨了它们各自的设计要点、模拟步骤及优化策略。此外,还分享了一些实用的编码示例和技术诀窍,帮助研究人员更好地理解和掌握相关技能。 适合人群:从事光学工程、光电子学等领域研究的专业人士,尤其是那些希望深入了解超表面偏振转换机制并对COMSOL有一定使用经验的技术人员。 使用场景及目标:适用于需要设计高性能偏振转换器件的研究项目,旨在提高对超表面特性的认识水平,推动新型光学组件的研发进程。通过学习本文提供的理论知识和实践经验,读者可以在实际工作中运用COMSOL完成高质量的仿真实验。 其他说明:文中不仅涵盖了基本的概念介绍,还包括了许多具体的实施细节,如参数选择、模型构建、边界条件设定等,这些都是成功搭建有效仿真的关键因素。同时,作者也强调了实验过程中可能出现的问题及解决方案,为后续研究提供了宝贵的参考资料。

    机器学习中萤火虫算法优化SVM模型参数的技术解析与应用

    内容概要:本文详细介绍了将萤火虫算法应用于支持向量机(SVM)模型参数优化的方法和技术细节。首先解释了萤火虫算法的基本原理及其在参数空间中的应用方式,然后展示了具体的Python实现代码,包括萤火虫移动规则、适应度评价函数以及主循环逻辑。文中还讨论了参数范围设定、随机扰动的作用、目标函数设计等多个关键技术点,并提供了多个数据集上的实验结果对比,证明了该方法的有效性和优越性。 适合人群:对机器学习尤其是SVM模型有一定了解的研究人员和工程师,希望掌握先进的超参数优化技术。 使用场景及目标:适用于需要提高SVM模型性能的项目中,特别是在面对大规模数据集或复杂特征空间的情况下。通过使用萤火虫算法进行参数寻优,可以显著减少调参时间和成本,获得更好的分类效果。 其他说明:文章不仅提供了理论依据,还有详细的代码示例可供参考。此外,作者强调了一些实用技巧如参数范围的选择、随机扰动的应用等,有助于读者更好地理解和应用这一技术。

    软考高级信息系统项目管理师考试题型解析与备考指南

    内容概要:本文详细介绍了软考高级信息系统项目管理师考试的内容,

    网络中间设备的发展及其在SDN/NFV环境下的角色转变与挑战

    内容概要:本文探讨了网络中间设备(middlebox)在现代网络架构中的地位和发展方向。首先介绍了网络中间设备的基本概念及其与传统转发设备的区别,强调了中间设备在网络安全、流量管理和优化方面的作用。接着讨论了软件定义网络(SDN)和网络功能虚拟化(NFV)背景下,中间设备面临的机遇和挑战,以及两者融合的趋势。最后展望了未来网流监控技术的发展前景,特别是在高效载荷过滤算法和敏捷策略管理机制方面的突破。 适合人群:从事网络工程、信息安全、云计算等领域工作的技术人员,以及对网络技术和架构感兴趣的科研人员。 使用场景及目标:帮助读者理解网络中间设备的关键作用和技术发展趋势,指导他们在实际工作中更好地规划和部署相关设备和服务。 其他说明:文中引用了SIGCOMM 2012和CoNEXT 2013的相关研究成果,提供了丰富的理论依据和技术背景支持。

    计算机二级各章考点.pdf

    计算机二级各章考点.pdf

    Tomcat 部署配置指南安全配置性能调优

    Tomcat 部署配置指南安全配置性能调优

    计算机辅助光学设计.pdf

    计算机辅助光学设计.pdf

    计算机二级考试机试(南开100题全).pdf

    计算机二级考试机试(南开100题全).pdf

    计算机二级VFP历年真题及答案.pdf

    计算机二级VFP历年真题及答案.pdf

    利用Python与PSS/E实现插电式电动汽车增强电网暂态稳定性的技术研究

    内容概要:本文探讨了利用插电式电动汽车(PEV)提高电网暂态稳定性的方法和技术。文中详细介绍了通过Python脚本与PSS/E软件的结合,实现对电网中发电机转速偏差的实时监测,并据此调整附近PEV的充放电功率,以快速响应电网扰动,保持系统稳定。具体措施包括设定合理的转速检测阈值、根据扰动强度非线性调整调节系数、动态调整仿真步长以及引入电池健康管理系统,确保PEV在提供辅助服务的同时不会因频繁充放电损害电池寿命。此外,还讨论了未来将更多分布式储能资源整合进电网的可能性。 适合人群:从事电力系统自动化、智能电网研究的专业人士,以及对电动汽车与电网互动感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解如何利用现代信息技术改善传统电力系统性能的研究机构或企业。主要目标是探索一种创新的技术路径,使得电动汽车不仅作为交通工具存在,还能成为电网稳定运行的重要组成部分。 其他说明:文中提到的方法已经在新英格兰39节点系统进行了初步验证,证明了其有效性。同时强调了通信延迟对于此类控制系统的影响,并提出了相应的解决办法。

    matlab可视化实现 包括:A算法、快速随机扩展树(RRT)算法、双向RRT、模糊逻辑算法、遗传算法(GA)、人工势场法、概率图路算法(PRM).zip

    matlab

Global site tag (gtag.js) - Google Analytics