聊到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
相关推荐
这份"Socket网络编程学习笔记"涵盖了从基础概念到高级技术的全面知识,对于初学者来说是一份非常有价值的参考资料。以下是对这份笔记内容的详细解读: 1. **Socket基本概念**:Socket在计算机网络中扮演着桥梁的...
### Socket网络编程基础知识点 #### 一、IP地址操作类详解 在进行Socket网络编程时,熟练掌握IP地址的操作是至关重要的。以下是两个关键的类:`IPAddress`和`IPEndPoint`。 ##### 1. `IPAddress`类 `IPAddress`...
本学习笔记将带你深入理解这一领域,特别是通过Socket接口进行的网络通信。Socket是操作系统提供的一种通信机制,它允许应用程序创建并管理网络连接,进行数据传输。 **TCP/IP协议族** TCP/IP(Transmission ...
Socket网络编程是构建分布式应用程序的基础,它允许两个网络上的进程之间进行双向通信。在本文中,我们将探讨在TCP...在后续的学习笔记中,作者还将探讨如何在消息中传递实体类信息,这将进一步扩展网络通信的能力。
### 基于TCP的Socket编程在VC中的应用与实现 #### 一、知识点概览 在VC(Visual C++)环境下进行网络编程时,基于TCP的socket编程是实现客户端与服务器之间通信的重要方式之一。本文将从初始化、创建socket、绑定...
在传统的Socket编程中,每当有新的客户端请求连接时,服务端通常会创建一个新的线程来处理该连接。虽然这种方法直观易懂,但频繁地创建和销毁线程会带来较大的系统开销,包括内存分配、上下文切换等。这对于高并发的...
网络通信基础知识,socket网络编程的一些基础知识,Socket网络编程学习笔记,网络编程总结,2011-学习资料大全:java_socket编程,学习网络编程的十个步骤,socket编程入门(经典版),Unix_网络编程学习笔记,...
本文主要探讨面向连接的TCP Socket编程,这是一种可靠的、基于连接的通信协议。 在TCP Socket编程中,服务端需要进行一系列步骤来建立一个监听Socket,以便接受来自客户端的连接请求。以下是一个基本的服务端TCP ...
本文主要探讨了Socket编程中的一些常见方法,特别是IP地址操作和DNS解析相关的类。 首先,我们关注`IPAddress`类,它是处理IP地址的核心类。`IPAddress.Parse()`方法允许将点分十进制的IP地址字符串转换为`IP...
Socket编程允许程序通过网络发送和接收数据,是实现网络通信的基础。在Linux环境下,Socket接口被广泛用于嵌入式设备的网络功能实现,因为它提供了标准且灵活的方式来处理TCP/IP协议。 首先,我们来了解一下IP地址...
在本篇《Socket网络编程学习笔记(3)c# yuanma》中,我们将深入探讨如何使用C#中的套接字助手类来简化Socket编程过程,使初学者更容易掌握网络编程的基本概念。本文主要围绕服务端的侦听模式、接收客户端连接以及如何...
本笔记主要探讨了IP地址操作、DNS解析以及如何在服务端建立Socket监听。 首先,IP地址操作涉及到`IPAddress`和`IPEndPoint`两个类。`IPAddress`类提供了对IP地址的处理能力,如`Parse()`方法可以将点分十进制的IP...
本篇学习笔记将深入探讨如何结合Socket与线程池来提升程序的运行效率。 一、Socket基础 Socket,也称为套接字,是网络编程中的一个重要概念,它是进程间通信(IPC)的一种方式,特别是在网络环境中。Socket提供了一...
在本学习笔记中,我们将探讨如何使用Java的Socket编程实现多线程服务器,特别是通过ExecutorService创建线程池来处理客户端的并发请求。ExecutorService是一个高级的线程管理工具,它允许我们更有效地管理和控制线程...
Socket网络编程是构建网络应用程序的基础,它允许两个设备在TCP/IP协议栈上进行通信。在本文中,我们将探讨如何在C#中使用Socket进行更复杂的通信,特别是涉及到类对象的序列化和网络传输。 首先,Socket通常用于...