‘壹’ iOS客户端与服务器的数据交互总结
前言:
本文总结了iOS客户端与服务器进行交互时,采用 RESTful API + Json 的交互方式,针对不 同的数据形式以及不同的解析方法,如有不足之处,欢迎指正。
先了解一下相关的基本概念。
HTTP通信:
即使用HTTP协议进行通信,工作原理是客户端向服务器端发送一条HTTP请求,服务器收到之后先 解析客户端的请求,之后会返回数据给客户端,然后客户端再对这些数据进行解析和处理。HTTP 连接采取的是“请求—响应”方式,即在请求时建立连接通道,当客户端像服务器端发送请求时,服 务器端才能向客户端发送数据。
Socket通信:Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信。通过建立 socket连接,可为通信双方的数据传输传提供通道。Socket的主要特点有数据丢失率低,使用简 单且易于移植。Socket类似于peer to peer的连接,一方可随时向另一方喊话。
小结:HTTP和Socket都是基于TCP协议的。使用两种通信方式的情况是: 使用HTTP的情况:双方不需要时刻保持连接在线,比如客户端资源的获取、文件上传等。
使用UDP的情况:大部分即时通讯应用(QQ、微信)、聊天室、苹果APNs等。
主要有四种:
数据流
1.从web服务器响应到手机终端的数据 一般打包在一个字节数组中,这个字节数据中包含了不同的 数据类型,客端端采取java数据流和过虑流的方式从字节数组中取出各种类型的数据。
这种交互方式我在学习iOS之初用过,实际项目中并没有发现哪家公司在用。这种方式了扩展 了iOS平台在访问Web服务器进行交互时的解析数据能力,仅供研究学习。
2.XML Webservice的标准数据格式。 Protocol Buffers
3.Protocol Buffers 是一种轻便高效的结构化数据存储格式,支持跨平台。它很适合做数据存储或 RPC 数据交换格式。比 JSON 最大的优点就是传输的时候数据体积可以压缩很小,传输效率比较 高。本人在这个在项目中没有用到过。
4.JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。毫无疑问,大家最常用。
本文重点会介绍关于Json数据格式 的常用格式。
Json数据格式 的采用,根据业务情况,一般是团队中的共识。技术的迭代更新,到后期基本都会考虑多 个平台的通用性、可移植性和可读性。比如 我们开发团队,有移动端开发(Android、iOS)、前端开发 (H5开发)和后台开发(golang开发)。
关于服务器的开发规范,我们先来了解一下。
服务器开发规范 我们采用的是 RESTful , RESTful 是目前最流流行的 API设计规范,用于web数据接
口的设计。
• 面面向资源(URI),具有解释性;
• 行为(GET / POST / PUT / PATCH / DELETE)与资源(URI)分离,更更加轻量量;
• 数据描述简单,使用用JSON、XML、Protocol Buffers即可全覆盖, 主要使用用JSON;
它的核心原则是定义用少量方法就能操作的命名资源。资源和方法可视为API的 和动词。
• GET :读取(Read)
• POST :新建(Create)
• PUT :更新(Update),通常是全部更更新
• PATCH :更新(Update),通常是部分更更新
• DELETE :删除(Delete)
项目搭建之始,客户端和服务器一般用 Get 和Post的方式来交互,随着业务的演进和技术的规范迭代, 到后期我们都得按规范来。于是 我们采用了上述几种方式来设计服务器接口,相应地,移动端的请求方 式也得与之对应。
至此,不在赘述 RESTful API 的设计规范,可自行网络了解更多。
接口的数据一般都采用JSON格式进行传输,不过,需要注意的是,JSON的值只有六种数据类型:
•Number:整数或浮点数
•String:字符串
•Boolean:true 或 false
•Array:数组包含在方括号 [] 中
•Object:对象包含在大括号 {} 中
•Null:空类型
传输的数据类型不能超过这六种数据类型,不能用Date数据类型,不同的解析库解析方式不同,可能会 导致异常,如果遇到日期的数据,最好的方式就是使用毫秒数表示日期。
本文总结了iOS与服务器的交互方式和数据类型,并总结了在实际项目的简单运用。数据格式的运
用场景远不止上面提到的几种场景,后期会持续完善,如有不足之处,欢迎指出。
‘贰’ web后台服务器是如何工作的
近期准备session,希望能跟大家轻松地分享一些东西,一些常见的场景。比如:web后台服务器到底是如何工作的。
上网过程对于普通人:首先,他需要一台电脑,然后,他的电脑可以接入网络,最后,他可以打开浏览器键入自己想要浏览的网址,然后就可以上网了。但是对于计算机来讲,是一个比较复杂的过程,里面包含了信息如何保存,信息如何传递以及信息如何展示的过程。所以,针对整个上网过程,我们从前到后,分析一下其中包含的各种技术细节,可能不全,目的是抛砖引玉,希望大家在简单的流程当中学习更多的东西分享出来,一些基础知识则当做复习。之前buddy王老吉讲过浏览器的工作方式,所以本文内容不包含浏览器的工作方式,重点在于各种后台服务以及通信层面的分析。
前面说到,用户浏览器中键入网址便浏览网页信息,这个网址实际上就是URL,英文全称是Uniform Resource Locator——统一资源定位符。
完整的、带有授权部分的普通统一资源标志符语法看上去如下:
协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值
协议部分可以是http,https,ftp等协议类型。
前面提到,互联网上的每个文件都有一个唯一的URL,那么,到底是如何确认的。前面提到了协议,协议是什么?比如大家写信时都需要写邮编、地址和姓名,便可以通过这种方式将信邮寄到世界上唯一的那个人手里,填写的邮编,地址和姓名就是一种协议。协议的价值在于世界上所有的浏览器和后台服务器都需要遵循http这些协议,才能正常进行信息的传递。
计算机通信跟人的通信是类似的,也是遵循各种协议的,不同的协议承载着不同的功能。通常,浏览器上网使用的是http或者https协议,从网络分层的角度来讲,这些协议属于应用层协议,建立在传输层之上。传输层跑是什么协议呢?相信大家都非常熟悉,传输层跑的是TCP和UDP协议,再往下就是网络层,网络层上面跑的是IP数据报。每层的功能各不相同,每层的协议也不同,但是一般来讲,越往下层,协议会越少,这样才能化繁为简,从而支持不同的上层协议。传输层协议一般是由操作系统层面支持的,同时还需要跟网络层进行交互(对于物理机来说就是网卡),所以针对我们操作系统之上的程序员来讲,新创造的协议都是应用层协议,因为我们的通信都是在传输层(TCP和UDP)基础之上构建的。
http是应用层协议,也就是说,在界面敲下网址那一刻,实际上浏览器向服务器发送了http协议格式的消息,也叫做http请求。http协议是构建在tcp协议之上的,而tcp是可靠的协议,所以http协议无需考虑可靠性,只管传输就可以了。
http协议比较简单,如下所示:
那么浏览器又是如何组织http请求,并且将信息发送的相应服务器的呢?例如: http://www..com
我们键入的仅仅是服务器域名,但是实际上在网络中我们通信是通过套接字来进行通信的。套接字=IP + 端口,在网络中,IP的作用是用来在网络层进行路由寻址,寻找唯一的主机;端口的作用是用来在这个主机中寻找唯一的进程。总体来说,套接字可以用来在网络中确定唯一主机的唯一进程,所以通过套接字我们可以进行通信。
但是问题是上网通过域名来访问,那么是如何通过域名来确认唯一主机的唯一后台web服务器进程的呢?做一个假设,如果我们可以在互联中提供一个确定的服务,这个服务里面装有域名到套接字的映射,上网的人通过这个服务获取对应域名的套接字,那么这个问题不就解决了。而实际上,DNS服务原理简单来说就是刚才假设的方法,服务商通过提供公共的DNS服务,大家上网时便可以查询到相应域名对应的套接字,通过这个套接字便可以访问确定的服务器了。真正的DNS服务其实更为复杂,分为迭代式查询和递归式查询,两种方式各有优劣,同时,为了性能,DNS服务通常也配有不同级别的缓存,关于DNS的具体实现有兴趣的可以自行查询资料学习。
总结一下,上网时浏览器实际上做了两件事,第一,通过浏览器内置的DNS客户端,向DNS服务器发送请求,获取域名对应套接字;第二,使用套接字发送http请求,获取数据,然后在浏览器端呈现。
另外,DNS服务也需要遵循某种协议才能通信,其协议为DNS协议,其服务固定为53端口,属于应用层协议。DNS英文为DomainNameSystem。其实DNS服务跟电话簿的工作方式一样,因为你没法记得每个人的电话号码,但是很容易记住每个人的名字。
上网前,我们的计算机里面什么都没有,为何键入网址后能在界面显示出各种各样的数据?实际上,数据都来自于后台服务器,所有的数据当然也都存储在后台服务器,浏览器仅仅请求数据。前面讲了,请求数据时,使用套接字加上http请求来获取数据,后台则必定要提供相应的套接字,接收信息,解析http请求,才能正常的返回客户端需要的数据。所以,后台服务器做的工作,第一,绑定套接字,通过该套接字向外提供http服务;第二,解析http请求,根据请求返回响应。
理论上讲,我们可以实现自己的http服务,并且解析不同的http请求,返回响应。但是,作为开发者来讲,重复造轮子是不推荐的,市面上有多种现成框架供我们选择。对于java开发者来讲,就有tomcat或者jetty,其他语言理论上也有类似的框架。tomcat和jetty帮我们做了什么呢?实际上最主要的功能还就是接受http请求,针对不同的请求返回响应,当然,他们也提供了更多的高级特性,比如遵循servlet规范,使人们更高效的开发web应用。
总结一下,上网的实际流程在程序员的角度来看,首先需要通过DNS服务解析域名,获取该域名所在web服务器应用程序的套接字,然后浏览器组装符合http协议的请求,通过套接字发送给web服务器,web服务器解析请求,根据解析结果将需要返回的内容组装符合http协议的响应,浏览器接到响应后,根据http协议解析响应,获取数据,将数据展示在浏览器上。
包含的知识点:DNS协议,HTTP协议,计算机网络知识,后台服务器实现(tomcat/jetty等)。
‘叁’ C++ 如何使用 Socket 类向 HTTP 服务器发送数据和接收响应
客户端发送请求给服务器,服务器处理完毕以后把Socket tempSocket = (你还可以检测收到的1W8数据是3W8里面的哪一部分. 这个把发送的数据和接收的
‘肆’ Ajax向服务器发送请求和接收返回的信息
Ajax向服务器发送请求
Ajax对象创建完成后,下面就要讲解一下Ajax如何使用。首先详细讲解一下Ajax向服务器发送请求所需的两个方法,具体如下:
(1)open()方法
open()方法用于创建一个新的HTTP请求,并指定此请求的类型(如GET、POST等)、URL以及验证信息,其声明方式如下所示:
在上述声明中,method用于指定请求的类型,其值可为POST、GET、PUT及PROPFIND,大小写不敏感;URL表示请求的地址,可以为绝对地址也可以为相对地址,并且可以传递查询字符串。其余参数为可选参数,其中,asyncFlagy用于指定请求方式,同步请求为false,默认为异步请求true;userName用于指定用户名,password用于指定密码。
(2)send()方法
send()方法用于发送请求到HTTP服务器并接收回应。其声明方式如下所示:
在上述声明中,content用于指定要发送的数据,其值可为DOM对象的实例、输入流或字符串,一般与POST请求类型配合使用,需要注意的是,如果请求声明为同步,该方法将会等待请求完成或者超时才会返回,否则此方法将立即返回。
需要注意的是,在使用GET方式传递特殊字符或中文参数时,要使用JavaScript中的encodeURIComponent()函数将其转换成“%十六进制数”的形式,防止在某些浏览器(如IE浏览器)中中文乱码的问题。
Ajax接收服务器返回的信息
了解Ajax向服务器发送请求后,下面将对Ajax如何接收服务器返回的信息(例如,HTML标签、CSS样式、字符串、XML、JSON等),进行详细讲解。具体如下:
(1)readyState属性
readyState属性用于返回Ajax的当前状态,状态值有5种形式,具体如表所示。
(2)onreadystatechange属性
onreadystatechange事件属性用于感知readyState属性状态的改变。为了大家更好的理解这两个属性的使用,下面创建一个服务器端的文件index.php,用于输出字符串,然后在浏览器端index.html中向服务器端发送请求,并在控制台输出状态值。具体示例如下所示:
创建服务器端文件:index.php
创建浏览器端文件:index.html
在浏览器中访问客户端文件,按“F12”键,切换到控制台,查看输出结果,具体如下图所示。
从图中可以看出,通过onreadystatechange事件属性可以清晰的感知Ajax状态的改变,同时使用readyState获取转变后的状态值。例如Ajax从0(未初始化)状态变成1(初始化)状态值时,Ajax此时的状态值为1。
(3)status属性
status属性用于返回当前请求的HTTP状态码,常见的状态码如表所示。
值得一提的是,在感知当前Ajax对象状态时,为了追求程序的严谨性,需要同时判断当前HTTP状态status是否等于200(请求成功)。
需要注意的是,Ajax中的statusText属性,仅当数据发送并接收完毕后,才可以获取当前请求的响应状态。
(4)获取响应信息的相关属性
当数据接收完毕且请求服务器的请求成功时,即可以使用Ajax中提供的相关属性获取服务器的响应信息。具体的属性及相关说明如下表所示。
在上表中,responseText属性用于返回文本格式的响应数据;属性responseBody表示直接从服务器返回并未经解码的二进制数据;responseXML属性用于接收XML数据格式的响应数据。
‘伍’ 服务器如何接收GPS定位器发送过来的数据
架设服务器平台,很简单;这里介绍一个 GPSBD卫星定位监控系统Simple版本的定位系统
他们系统是JAVA开发,首先服务器需要搭建JAVA环境,Mysql数据库,以及Reids缓存服务;
然后启动程序文件,一步一步操作即可;经过测试系统基本上市面上的各类GPS北斗定位设备都是支持的
在自己服务器搭建好GPS平台以后,就可以将设备的IP 端口配置到自己服务器对应的IP端口上,这样设备数据就会发往服务器,然后通过这套GPS定位系统就可以查看位置了
‘陆’ java socket编程,客户端发送文件给服务器,服务器接收到文件后如何返回确认信息告诉客户端文件已接收
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.net.ServerSocket;
importjava.net.Socket;
/**
*
*文件名:ServerReceive.java
*实现功能:作为服务器接收客户端发送的文件
*
*具体实现过程:
*1、建立SocketServer,等待客户端的连接
*2、当有客户端连接的时候,按照双方的约定,这时要读取一行数据
*其中保存客户端要发送的文件名和文件大小信息
*3、根据文件名在本地创建文件,并建立好流通信
*4、循环接收数据包,将数据包写入文件
*5、当接收数据的长度等于提前文件发过来的文件长度,即表示文件接收完毕,关闭文件
*6、文件接收工作结束
*简大
*
*【注:此代码仅为演示客户端与服务器传送文件使用,
*每一个数据包之前没有文件协议命令
*具体的协议传输和文件传出的使用阶段可根据自己程序自行放置】
*
*
*作者:小菜鸟
*创建时间档氏:2014-08-19
*
行咐散**/
publicclassServerReceive{
publicstaticvoidmain(String[]args){
/**与服务器建立连接的通信句柄*/
ServerSocketss=null;
Sockets=null;
/**定义用于在接收后在本地创建的文件对象和文件输出流对象*/
Filefile=null;
FileOutputStreamfos=null;
/**定义输入流,使用socket的inputStream对数据包进行输入*/
InputStreamis=null;
/**定义byte数组来作为数据包的存储数据包*/
byte[]buffer=newbyte[4096*5];
/**用来接收文件发送请求的字符串*/
Stringcomm=null;
/**建立socekt通信,等待服务器进行连接*/
try{
ss=newServerSocket(4004);
s=ss.accept();
}catch(IOExceptione){
e.printStackTrace();
}
/**读取一行客户端发送过来的约定信息*/
try{
InputStreamReaderisr=newInputStreamReader(s.getInputStream());
BufferedReaderbr=newBufferedReader(isr);
comm=br.readLine();
}catch(IOExceptione){
System.out.println("服务器与客户端断开连接");
}
/**开始解析客户端发送过来的请求命令*/
intindex=comm.indexOf("/#");
/**判断协议是否为发送文件的协议*/
Stringxieyi=comm.substring(0,index);
if(!xieyi.equals("111")){
System.out.println("服务器收到的协议码不正确");
return;
}
/**解析出文件的名字和大小*/
comm=comm.substring(index+2);
index=comm.indexOf("/#");
Stringfilename=comm.substring(0,index).trim();
Stringfilesize=comm.substring(index+2).trim();
/**创建空文件,用来进行接收文件*/
file=newFile(filename);
if(!file.exists()){
try{
file.createNewFile();
}catch(IOExceptione){
System.out.println("服务器端创建文件失败");
}
}else{
/**在此也可以询问是否覆盖*/
System.out.println("本路径已存在相同文件,进行覆盖");
}
/**【以上就是客户端代码中写到的服务器的准备部分】*/
/**
*服务器接收文件的关键代码*/
try{
/**将文件包装到文件输出流对象中*/
fos=newFileOutputStream(file);
longfile_size=Long.parseLong(filesize);
is=s.getInputStream();
/**size为每次接收数据包的长度*/
intsize=0;
/**count用来记录已接收到文件的长度*/
longcount=0;
/**使用while循环接收数据包*/
while(count<file_size){
/**从输入流中读取一个数据包*/
size=is.read(buffer);
/**将刚刚读取的数据包写到本地文件中去*/
fos.write(buffer,0,size);
fos.flush();
/**将已接收到文件的长度+size*/
count+=size;
System.out.println("服务器端接收到数据包,大小为"+size);
}
}catch(FileNotFoundExceptione){
System.out.println("服务器写文件失败");
}catch(IOExceptione){
System.out.println("服务器:客户端断开连接");
}finally{
/**
*将打开的文件关闭
*如有需要,也可以在此关闭socket连接
**/
try{
if(fos!=null)
fos.close();
}catch(IOExceptione){
e.printStackTrace();
}//catch(IOExceptione)
}//finally
}//publicstaticvoidmain(String[]args)
}//publicclassServerReceive