`

TCP/IP通讯(二)

阅读更多

本文主要关注点:

 问:TCP方式的socket通讯的接受者不知道或者说无法确定消息的长度(比如我们聊天消息 前后的消息长度可能是不一样的),如果能识别消息是否接受完成

答:主要有2中技术使接受者能够准确的找到消息的结束位置

       1、基于鉴定符(Delimiter-base):消息的结束由一个唯一的标记支出,即发送者在传输完数据后显式添加一个特殊字节序列。这个特殊标记不能砸传输中数据中出现

        2、显式长度(Explicit length):在边长字段货消息前附加一个固定大小的字段,用来指示该字段货消息中包含了多少个字节(这个方法简单些,不过必须知道消息的长度的上限。发送者先确定消息的长度,将长度信息存入一个整数,作为消息的前缀。消息的藏毒上限定义了编码消息藏毒所需要的字节数:如果消息的长度小于256字节,则需要1个字节;如果消息的长度消息65536字节,则需要2个字节)

 

追问:第一个技术中,假如消息体重出现特殊标记字符怎么办

          答:填充(Stuffing)技术能够对消息中出现的定界符进行修改,聪哥使接受者不将其识别为界定符。这个有个缺点是发送者和接受者双方度必须扫描消息

       

 

2、通讯要成功并且2端都能正确解析,需要通讯的双发约定协议:即命令交互的格式。

 

以下文投票为例:我们需要服务端和客户端约定一套规则来识别是投票、查询还是响应

一般2中表示方式  基本文本的表示方式(投票示例,按约定规则生成和解析字符串)和二进制表示方式

 

package cc.leng.tcpip.step2;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
/**
 * 投票编解码<br/>
 * format: Voting <"v"|"i"> [<RESPFLAG> <CANDIADTEID> [VOTECNT]
 * @author leng-home
 *
 */
public class VoteMsgTextCoder {

	public static final String MAGIC = "Voting";
	public static final String VOTESTR = "v";
	public static final String INQSTR = "i";
	public static final String RESPONSESTR = "R";
	public static final String CHARSETNAME = "US_ASCII";
	public static final String DELIMSTR = " ";
	public static final int MAX_WIRE_LENGTH = 2000;

	/**
	 * 
	 * @param msg
	 * @return
	 * @throws IOException
	 */
	public byte[] toWire(VoteMsg msg) throws IOException {
		StringBuilder sb = new StringBuilder();
		sb.append(MAGIC).append(DELIMSTR)
				.append((msg.isInquiry() ? INQSTR : VOTESTR)).append(DELIMSTR)
				.append(msg.isResponse() ? RESPONSESTR + DELIMSTR : "")
				.append(msg.getCandidateID()).append(DELIMSTR)
				.append(msg.getVoteCount());
		byte[] data = sb.toString().getBytes(CHARSETNAME);
		
		return data;

	}
	/**
	 * 
	 * @param mesage
	 * @return
	 * @throws IOException
	 */
	public VoteMsg fromWire(byte[] mesage) throws IOException{
		ByteArrayInputStream msgStream = new ByteArrayInputStream(mesage);
		Scanner s = new Scanner(new InputStreamReader(msgStream,CHARSETNAME));
		boolean isInquiry;
		boolean isResponse;
		int candidateID;
		long voteCount;
		String token;
		try{
			token = s.next();
			if(!MAGIC.equals(token)){
				throw new IOException("Bad magic string : "+ token);
			}
			token = s.next();
			if(VOTESTR.equals(token)){
				isInquiry = false;
			}else if(!INQSTR.equals(token)){
				throw new IOException("Bad vote/inq indicator :"+token);
			}else{
				isInquiry = true;
			}
			
			token = s.next();
			
			if(RESPONSESTR.equals(token)){
				isResponse = true;
				token = s.next();
			}else{
				isResponse = false;
			}
			//current token is candidateID
			candidateID = Integer.parseInt(token);
			if(isResponse){
				token = s.next();
				voteCount = Long.parseLong(token);
			}else{
				voteCount = 0;
			}
		}catch(IOException e){
			throw new IOException("parse error....");
		}
		return new VoteMsg(isResponse, isInquiry, candidateID, voteCount);
	}
}

 

package cc.leng.tcpip.step2;

/**
 * 投票信息类
 * @author leng-home
 *
 */
public class VoteMsg {
	
	private boolean isInquiry;
	private boolean isResponse;
	private int candidateID;
	private long voteCount;
	
	
	public static final int MAX_CANDIDATE_ID = 1000;
	
	public VoteMsg(boolean isResponse,boolean isInquiry,int candidateID,long voteCount){
		if(voteCount !=0 && !isResponse){
			//只有响应的时候voteCount才有值
			throw new IllegalArgumentException("Request vote count must be zero");
		}
		if(candidateID < 0 || candidateID > MAX_CANDIDATE_ID){
			throw new IllegalArgumentException("Bad Candidate ID: " + candidateID);
		}
		if(voteCount < 0){
			throw new IllegalArgumentException("Total must be >= zero");
		}
		this.candidateID = candidateID;
		this.isResponse = isResponse;
		this.isInquiry = isInquiry;
		this.voteCount = voteCount;
	}
	
	

	public boolean isInquiry() {
		return isInquiry;
	}

	public void setInquiry(boolean isInquiry) {
		this.isInquiry = isInquiry;
	}

	public boolean isResponse() {
		return isResponse;
	}

	public void setResponse(boolean isResponse) {
		this.isResponse = isResponse;
	}

	public int getCandidateID() {
		return candidateID;
	}

	public void setCandidateID(int candidateID) {
		this.candidateID = candidateID;
	}

	public long getVoteCount() {
		return voteCount;
	}

	public void setVoteCount(long voteCount) {
		this.voteCount = voteCount;
	}
	
	
	public String toString() {
		String res = (isInquiry ? "inquiry" : "vote") + " for candidate "+ candidateID;
		if(isResponse){
			res = " response to" + res + " who now has " + voteCount + " vote(s)";
		}
		return res;
	}
	

}

 

 

 

分享到:
评论

相关推荐

    三菱FX5UJ和艾莫迅远程模块实现TCP/IP通讯,程序包含多种功能吗的实现

    首先,我们要理解TCP/IP通讯的基础,然后逐步解析源码软件的实现细节。 TCP/IP(传输控制协议/因特网协议)是一种标准网络通信协议,它定义了数据在网络中的传输方式,包括网络层的IP协议,负责数据包的路由,以及...

    基于mfc智能设备的tcp/ip通讯

    本项目“基于MFC智能设备的TCP/IP通讯”旨在通过MFC库开发一个简单的通讯软件,使PC机能够与使用MFC的智能设备进行高效的数据交换。 首先,我们需要了解MFC如何处理TCP/IP通讯。在MFC中,网络编程通常涉及CSocket类...

    比较完整的TCP/IP通讯实例

    本实例“比较完整的TCP/IP通讯实例”提供了一个全面的参考,涵盖了Server端和Client端的编程实现,适用于开发者根据自身需求进行扩展。 TCP/IP协议栈分为四层(在OSI七层模型中对应为五层):应用层、传输层、网络...

    C#实现串口通讯和TCP/IP通讯的示例程序

    本示例程序聚焦于C#实现串口通讯和TCP/IP通讯,这两大通信方式在工业自动化、物联网(IoT)和嵌入式系统中扮演着核心角色。 **串口通讯**(Serial Communication)是指通过串行接口进行数据传输。在C#中,我们可以...

    KUKA机器人TCIP/IP通讯

    库卡(KUKA)机器人TCP/IP通讯是工业自动化领域中的一个重要知识点,它涉及了现代机器人控制技术、网络通信协议以及编程接口等多个方面。在这个专题中,我们将深入探讨如何利用TCP/IP协议与KUKA机器人进行高效、稳定...

    C# TCP/IP通信小例子

    本示例"**C# TCP/IP通信小例子**"是一个基础教程,旨在帮助新手理解如何在C#中实现TCP/IP通信。 TCP(传输控制协议)和IP(因特网协议)是Internet上最基础的通信协议,TCP负责确保数据的可靠传输,而IP则处理...

    TCP/IP通讯技术

    MFC例子TCP/IP通讯技术

    PB9+TCP/ip通讯服务利用winSocket的例子(简单,测试通过)

    标题 "PB9+TCP/ip通讯服务利用winSocket的例子(简单,测试通过)" 指的是一个使用PowerBuilder 9(PB9)编程语言,并结合Windows Socket API(通常称为winSocket)实现TCP/IP通信的示例项目。这个项目已经过测试并确认...

    STM32 tcp/ip通讯

    TCP/IP通讯是STM32实现网络功能的基础,允许设备通过互联网与其他设备进行数据交换。本文将深入探讨STM32如何实现TCP/IP通信,并基于提供的"STM32 tcp/ip通讯"项目,分析其代码和步骤。 首先,TCP/IP协议栈是STM32...

    串口通讯和TCP/IP通讯程序

    串口通讯和TCP/IP通讯是两种常见的数据通信方式,在信息技术领域有着广泛的应用。它们各自有其特点和适用场景,理解并掌握这两种通讯方式对于IT专业人员来说至关重要。 串口通讯,也称为UART(通用异步收发传输器)...

    tcp/ip通讯方式实现聊天源码

    TCP/IP通讯方式是互联网通信的基础,它是一种分层的网络通信模型,由四层组成:应用层、传输层、网络层和数据链路层。在这个模型中,每一层都有其特定的功能,为上层提供服务并向下层传递数据。本项目以"tcp/ip通讯...

    基于socket应用的TCP/Ip通讯

    在IT领域,网络通信是至关重要的组成部分,而TCP/IP通讯协议族则是互联网通信的基础。本文将深入探讨基于Socket应用的TCP/IP通讯,包括其工作原理、实现方式以及如何通过服务端和客户端进行交互。 首先,TCP...

    s7-300的tcp/ip协议通讯

    ### S7-300的TCP/IP协议通讯 #### 概述 SIMATIC S7-300系列的CPU集成了PROFINET接口,不仅支持PROFINET总线通信,还可以用于标准的TCP/IP通信。这使得S7-300能够通过组态TCP连接以及使用开放式通信的功能块与其他...

    C#编写的局域网通讯 TCP/IP

    8. **以太网通讯**: 以太网是局域网最常用的通信标准,C#的TCP/IP通信默认就是在以太网上进行的。以太网提供了物理层和数据链路层的规范,确保数据能在局域网中正确传输。 9. **防火墙与端口转发**: 在实际环境中,...

    PLC通过TCP/IP协议通信实例C#源码

    TCP/IP协议作为互联网的基础,具有稳定、可靠的特性,非常适合在工业环境中用于设备间的通讯。 首先,我们需要理解TCP/IP协议栈的四层模型:应用层、传输层、网络层和数据链路层。在PLC通信中,我们主要关注应用层...

    Delphi TCP/IP通信

    TCP/IP通信是网络编程的基础,它允许不同计算机之间的数据交换。在Delphi中,通过使用内置的Internet组件,如ServerSocket和ClientSocket,开发者可以轻松实现TCP/IP通信。 ServerSocket组件代表服务器端,用于监听...

    Tcp/Ip通讯程序

    《TCP/IP通信程序详解》 TCP/IP通信协议是互联网上最基础、最重要的通信协议之一,它定义了数据在网络中传输的规则和格式。本程序示例展示了两台计算机如何利用TCP/IP进行点对点的通信,这对于理解网络编程原理以及...

    tcp-udp.rar_C语言tcp/ip通讯_TCP IP C语言_TCP/ip c语言_c语言 tcp_tcp/ip c语

    下面我们将详细探讨TCP/IP协议栈、C语言实现TCP/IP通信的原理以及TCP与UDP的区别。 TCP/IP协议栈是一个分层模型,包括应用层、传输层、网络层和数据链路层。应用层负责定义各种网络应用,如HTTP、FTP等;传输层处理...

    TCP/IP通信c#例程

    在IT行业中,网络通信是至关重要的一个领域,TCP/IP(Transmission Control Protocol/Internet Protocol)协议栈则是互联网通信的基础。本文将深入探讨C#语言中实现TCP/IP通信的相关知识点,通过实例来阐述如何创建...

Global site tag (gtag.js) - Google Analytics