android getpost如何实现多参数请求
可使用android自带的httpclient框架实现。
GET 方式传递参数
//先将参数放入List,再对参数进行URL编码
List<BasicNameValuePair> params = new LinkedList<BasicNameValuePair>();
paramsadd(new BasicNameValuePair("param1", "数据")); //增加参数1
paramsadd(new BasicNameValuePair("param2", "value2"));//增加参数2
String param = URLEncodedUtilsformat(params, "UTF-8");//对参数编码
String baseUrl = "服务器接口完整URL";
HttpGet getMethod = new HttpGet(baseUrl + "" + param);//将URL与参数拼接
HttpClient httpClient = new DefaultHttpClient();
try {
HttpResponse response = httpClientexecute(getMethod); //发起GET请求
Logi(TAG, "resCode = " + responsegetStatusLine()getStatusCode()); //获取响应码
Logi(TAG, "result = " + EntityUtilstoString(responsegetEntity(), "utf-8"));//获取服务器响应内容
} catch (ClientProtocolException e) {
eprintStackTrace();
} catch (IOException e) {
eprintStackTrace();
}
2 POST方式 方式传递参数
//和GET方式一样,先将参数放入List
params = new LinkedList<BasicNameValuePair>();
paramsadd(new BasicNameValuePair("param1", "Post方法"));//增加参数1
paramsadd(new BasicNameValuePair("param2", "第二个参数"));//增加参数2
try {
HttpPost postMethod = new HttpPost(baseUrl);//创建一个post请求
postMethodsetEntity(new UrlEncodedFormEntity(params, "utf-8")); //将参数填入POST Entity中
HttpResponse response = httpClientexecute(postMethod); //执行POST方法
Logi(TAG, "resCode = " + responsegetStatusLine()getStatusCode()); //获取响应码
Logi(TAG, "result = " + EntityUtilstoString(responsegetEntity(), "utf-8")); //获取响应内容
} catch (UnsupportedEncodingException e) {
eprintStackTrace();
} catch (ClientProtocolException e) {
eprintStackTrace();
} catch (IOException e) {
eprintStackTrace();
}
如何实现网页和app之间的无缝跳转?
没有办法从网页无缝跳转到app,会弹出提示。app与服务器交互方式?
最近的Android项目开发过程中一个问题困扰自己很长时间,Android客户端与服务器交互有几种方式,最常见的就是webservices和json。要在Android手机客户端与pc服务器交互,需要满足下面几种条件:跨平台、传输数据格式标准、交互方便。
为了与服务器通讯其实无非就两种协议HTTP和TCP,TCP的学习Socket,HTTP的话熟悉一下HTTP协议和相关JavaAPI。而下面的几种方式就是从这两种协议扩展出来的:webservicessoap、SSH的JSON(可参考:该链接)、xmlrpc(wordpressforandroid)
Socket不推荐,HTTPRESTful推荐。跟服务器传数据的话,一般都是采用RESTfulAPI来传输。这样首先要对HTTP协议有初步的理解,至少知道GET/POST分别是干嘛的有什么区别。
如果没有特殊要求,使用webservices传输XML文件比较简单及通用,如果对数据大小及传输速度有要求的话就用json更合适。
Socket与HTTP连接的区别
HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
socket是可以监听,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。保持客户端与服务器数据的实时与同步。
xmlrpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据。
RPC是RemoteProcedureCall的缩写,翻译成中文就是远程过程调用,是一种在本地的机器上调用远端机器上的一个过程(方法)的技术,这个过程也被大家称为“分布式计算”
web前端怎么与后端交互?
个人理解,前端与后端的交互就是数据传递的过程通过ajax请求获取需要的数据在自己的前端页面展现出来,或者将前端表单的数据通过请求发送给后端
如何通过浏览器与web服务器进行数据交互的?
登陆远程到服务器。就和数据交换或服务器管理。
web和数据库数据交互是用的什么协议?
webServer与数据库进行数据交互用的是HTTP协议。
HTTP协议是HyperTextTransferProtocol(超文本传输协议)的缩写。HTTP协议和TCP/IP协议族内的其他众多的协议相同,
用于客户端和服务器之间的通信。请求访问文本或图像等资源的一端称为客户端,
而提供资源响应的一端称为服务器端。
web交互有什么优点?
一、Web是图形化的和易于导航的(navigate)
Web非常流行的一个很重要的原因就在于它可以在一页上同时显示色彩丰富的图形和文本的性能。在Web之前Internet上的信息只有文本形式。Web可以提供将图形、音频、视频信息集合于一体的特性。同时,Web是非常易于导航的,只需要从一个连接跳到另一个连接,就可以在各页各站点之间进行浏览了。
二、Web与平台无关
无论你的系统平台是什么,你都可以通过Internet访问WWW。浏览WWW对你的系统平台没有什么限制。无论从Windows平台、UNIX平台、Macintosh还是别的什么平台我们都可以访问WWW。对WWW的访问是通过一种叫做浏览器(browser)的软件实现的。如Netscape的Navigator、NCSA的Mosaic、Microsoft的Explorer等。
三、Web是分布式的
大量的图形、音频和视频信息会占用相当大的磁盘空间,我们甚至无法预知信息的多少。对于Web没有必要把所有信息都放在一起,信息可以放在不同的站点上。只需要在浏览器中指明这个站点就可以了。使在物理上并不一定在一个站点的信息在逻辑上一体化,从用户来看这些信息是一体的。
四、Web是动态的
最后,由于各Web站点的信息包含站点本身的信息,信息的提供者可以经常对站上的信息进行更新。如某个协议的发展状况,公司的广告等等。一般各信息站点都尽量保证信息的时间性。所以Web站点上的信息是动态的。经常更新的。这一点是由信息的提供者保证的。
五、Web是交互的
Web的交互性首先表现在它的超连接上,用户的浏览顺序和所到站点完全由他自己决定。另外通过FORM的形式可以从服务器方获得动态的信息。用户通过填写FORM可以向服务器提交请求,服务器可以根据用户的请求返回相应信息。
android中网络通信分为socket编程和http编程,这里只介绍htt方面。网络请求方式可分为get请求,post两种请求方式,GET方式在进行数据请求时,会把数据附加到URL后面传递给服务器,比如常见的:http://XXXXXXXXX/XXaspxid=1,POST方式则是将请求的数据放到HTTP请求头中,作为请求头的一部分传入服务器。
所以,在进行HTTP编程前,首先要明确究竟使用的哪种方式进行数据请求的。
android中Http编程有两种:1、HttpURLConnection;2、HttpClient
首先介绍一下HttpURLConnection方式的get请求和post请求方法:
[java] view
plaincopyprint
private Map<String, String> paramsValue;
String urlPath=null;
// 发送地http://19216810091:8080/myweb/loginusername=abc&password=123
public void initData(){
urlPath="http://19216810091:8080/myweb/login";
paramsValue=new HashMap<String, String>();
paramsValueput("username", "111");
paramsValueput("password", "222");
}
private Map<String, String> paramsValue;
String urlPath=null;
// 发送地http://19216810091:8080/myweb/loginusername=abc&password=123
public void initData(){
urlPath="http://19216810091:8080/myweb/login";
paramsValue=new HashMap<String, String>();
paramsValueput("username", "111");
paramsValueput("password", "222");
}
get方式发起请求:
[java] view
plaincopyprint
private boolean sendGETRequest(String path, Map<String, String> params) throws Exception {
boolean success=false;
// StringBuilder是用来组拼请求地址和参数
StringBuilder sb = new StringBuilder();
sbappend(path)append("");
if (params != null && paramssize() != 0) {
for (MapEntry<String, String> entry : paramsentrySet()) {
// 如果请求参数中有中文,需要进行URLEncoder编码 gbk/utf8
sbappend(entrygetKey())append("=")append(URLEncoderencode(entrygetValue(), "utf-8"));
sbappend("&");
}
sbdeleteCharAt(sblength() - 1);
}
URL url = new URL(sbtoString());
HttpURLConnection conn = (HttpURLConnection) urlopenConnection();
connsetConnectTimeout(20000);
connsetRequestMethod("GET");
if (conngetResponseCode() == 200) {
success= true;
}
if(conn!=null)
conndisconnect();
return success;
}
private boolean sendGETRequest(String path, Map<String, String> params) throws Exception {
boolean success=false;
// StringBuilder是用来组拼请求地址和参数
StringBuilder sb = new StringBuilder();
sbappend(path)append("");
if (params != null && paramssize() != 0) {
for (MapEntry<String, String> entry : paramsentrySet()) {
// 如果请求参数中有中文,需要进行URLEncoder编码 gbk/utf8
sbappend(entrygetKey())append("=")append(URLEncoderencode(entrygetValue(), "utf-8"));
sbappend("&");
}
sbdeleteCharAt(sblength() - 1);
}
URL url = new URL(sbtoString());
HttpURLConnection conn = (HttpURLConnection) urlopenConnection();
connsetConnectTimeout(20000);
connsetRequestMethod("GET");
if (conngetResponseCode() == 200) {
success= true;
}
if(conn!=null)
conndisconnect();
return success;
}
postt方式发起请求:
[java] view
plaincopyprint
private boolean sendPOSTRequest(String path,Map<String, String> params) throws Exception{
boolean success=false;
//StringBuilder是用来组拼请求参数
StringBuilder sb = new StringBuilder();
if(params!=null &¶mssize()!=0){
for (MapEntry<String, String> entry : paramsentrySet()) {
sbappend(entrygetKey())append("=")append(URLEncoderencode(entrygetValue(), "utf-8"));
sbappend("&");
}
sbdeleteCharAt(sblength()-1);
}
//entity为请求体部分内容
//如果有中文则以UTF-8编码为username=%E4%B8%AD%E5%9B%BD&password=123
byte[] entity = sbtoString()getBytes();
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) urlopenConnection();
connsetConnectTimeout(2000);
// 设置以POST方式
connsetRequestMethod("POST");
// Post 请求不能使用缓存
// urlConnsetUseCaches(false);
//要向外输出数据,要设置这个
connsetDoOutput(true);
// 配置本次连接的Content-type,配置为application/x-www-form-urlencoded
//设置content-type获得输出流,便于想服务器发送信息。
//POST请求这个一定要设置
connsetRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connsetRequestProperty("Content-Length", entitylength+"");
// 要注意的是connectiongetOutputStream会隐含的进行connect。
OutputStream out = conngetOutputStream();
//写入参数值
outwrite(entity);
//刷新、关闭
outflush();
outclose();
if (conngetResponseCode() == 200) {
success= true;
}
if(conn!=null)
conndisconnect();
return success;
}
private boolean sendPOSTRequest(String path,Map<String, String> params) throws Exception{
boolean success=false;
//StringBuilder是用来组拼请求参数
StringBuilder sb = new StringBuilder();
if(params!=null &¶mssize()!=0){
for (MapEntry<String, String> entry : paramsentrySet()) {
sbappend(entrygetKey())append("=")append(URLEncoderencode(entrygetValue(), "utf-8"));
sbappend("&");
}
sbdeleteCharAt(sblength()-1);
}
//entity为请求体部分内容
//如果有中文则以UTF-8编码为username=%E4%B8%AD%E5%9B%BD&password=123
byte[] entity = sbtoString()getBytes();
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) urlopenConnection();
connsetConnectTimeout(2000);
// 设置以POST方式
connsetRequestMethod("POST");
// Post 请求不能使用缓存
// urlConnsetUseCaches(false);
//要向外输出数据,要设置这个
connsetDoOutput(true);
// 配置本次连接的Content-type,配置为application/x-www-form-urlencoded
//设置content-type获得输出流,便于想服务器发送信息。
//POST请求这个一定要设置
connsetRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connsetRequestProperty("Content-Length", entitylength+"");
// 要注意的是connectiongetOutputStream会隐含的进行connect。
OutputStream out = conngetOutputStream();
//写入参数值
outwrite(entity);
//刷新、关闭
outflush();
outclose();
if (conngetResponseCode() == 200) {
success= true;
}
if(conn!=null)
conndisconnect();
return success;
}
在介绍一下HttpClient方式,相比HttpURLConnection,HttpClient封装的得更简单易用一些,看一下实例:
get方式发起请求:
[java] view
plaincopyprint
public String getRequest(String UrlPath,Map<String, String> params){
String content=null;
StringBuilder buf = new StringBuilder();
if(params!=null &¶mssize()!=0){
for (MapEntry<String, String> entry : paramsentrySet()) {
bufappend(entrygetKey())append("=")append(URLEncoderencode(entrygetValue(), "utf-8"));
bufappend("&");
}
bufdeleteCharAt(buflength()-1);
}
content= buftoString();
HttpClient httpClient = new DefaultHttpClient();
HttpGet getMethod = new HttpGet(content);
HttpResponse response = null;
try {
response = httpClientexecute(getMethod);
} catch (ClientProtocolException e) {
eprintStackTrace();
} catch (IOException e) {
eprintStackTrace();
}catch (Exception e) {
eprintStackTrace();
}
if (response!=null&&responsegetStatusLine()getStatusCode() == HttpStatusSC_OK) {
try {
content = EntityUtilstoString(responsegetEntity());
} catch (ParseException e) {
eprintStackTrace();
} catch (IOException e) {
eprintStackTrace();
}
}
return content;
}
public String getRequest(String UrlPath,Map<String, String> params){
String content=null;
StringBuilder buf = new StringBuilder();
if(params!=null &¶mssize()!=0){
for (MapEntry<String, String> entry : paramsentrySet()) {
bufappend(entrygetKey())append("=")append(URLEncoderencode(entrygetValue(), "utf-8"));
bufappend("&");
}
bufdeleteCharAt(buflength()-1);
}
content= buftoString();
HttpClient httpClient = new DefaultHttpClient();
HttpGet getMethod = new HttpGet(content);
HttpResponse response = null;
try {
response = httpClientexecute(getMethod);
} catch (ClientProtocolException e) {
eprintStackTrace();
} catch (IOException e) {
eprintStackTrace();
}catch (Exception e) {
eprintStackTrace();
}
if (response!=null&&responsegetStatusLine()getStatusCode() == HttpStatusSC_OK) {
try {
content = EntityUtilstoString(responsegetEntity());
} catch (ParseException e) {
eprintStackTrace();
} catch (IOException e) {
eprintStackTrace();
}
}
return content;
}
postt方式发起请求:
[java] view
plaincopyprint
private boolean sendPOSTRequestHttpClient(String path,Map<String, String> params) throws Exception {
boolean success = false;
// 封装请求参数
List<NameValuePair> pair = new ArrayList<NameValuePair>();
if (params != null && !paramsisEmpty()) {
for (MapEntry<String, String> entry : paramsentrySet()) {
pairadd(new BasicNameValuePair(entrygetKey(), entry
getValue()));
}
}
// 把请求参数变成请求体部分
UrlEncodedFormEntity uee = new UrlEncodedFormEntity(pair, "utf-8");
// 使用HttpPost对象设置发送的URL路径
HttpPost post = new HttpPost(path);
// 发送请求体
postsetEntity(uee);
// 创建一个浏览器对象,以把POST对象向服务器发送,并返回响应消息
DefaultHttpClient dhc = new DefaultHttpClient();
HttpResponse response = dhcexecute(post);
if (responsegetStatusLine()getStatusCode() == 200) {
success = true;
}
return success;
}
private boolean sendPOSTRequestHttpClient(String path,Map<String, String> params) throws Exception {
boolean success = false;
// 封装请求参数
List<NameValuePair> pair = new ArrayList<NameValuePair>();
if (params != null && !paramsisEmpty()) {
for (MapEntry<String, String> entry : paramsentrySet()) {
pairadd(new BasicNameValuePair(entrygetKey(), entry
getValue()));
}
}
// 把请求参数变成请求体部分
UrlEncodedFormEntity uee = new UrlEncodedFormEntity(pair, "utf-8");
// 使用HttpPost对象设置发送的URL路径
HttpPost post = new HttpPost(path);
// 发送请求体
postsetEntity(uee);
// 创建一个浏览器对象,以把POST对象向服务器发送,并返回响应消息
DefaultHttpClient dhc = new DefaultHttpClient();
HttpResponse response = dhcexecute(post);
if (responsegetStatusLine()getStatusCode() == 200) {
success = true;
}
return success;
}
由身份或持有的令牌确认享有的权限,登录过程实质上的目的也是为了确认权限。
Cookie是客户端给服务器用的,setCookie是服务器给客户端用的。cookie由服务器处理,客户端负责存储
客户端发送cookie:账户和密码
服务端收到后确认登录setCookie:sessionID=1,记下sessionID
客户端收到sessionID后记录,以后请求服务端带上对比记录下sessionID,说明已经登录
会话管理:登录状态,购物车
个性化:用户偏好,主题
Tracking:分析用户行为
XXS:跨脚本攻击,及使用JavaScript拿到浏览器的cookie之后,发送到自己的网站,以这种方式来盗用用户Cookie。Server在发送Cookie时,敏感的Cookie加上HttpOnly,这样Cookie只能用于http请求,不能被JavaScript调用
XSRF:跨站请求伪造。Referer 从哪个网站跳转过来
两种方式:Basic和Bearer
首先第三方网站向授权网站申请第三方授权合作,拿到授权方颁发的client_id和client_secret(一般都是appid+appkey的方式)。
在这就过程中申请的client_secret是服务器持有的,安全起见不能给客户端,用服务端去和授权方获取用户信息,再传给客户端,包括④,⑤的请求过程也是需要加密的。这才是标准的授权过程。
有了access_token之后,就可以向授权方发送请求来获取用户信息
步骤分析就是上面的内容,这里把第4,6,8请求的参数分析一下
第④步参数:
response_type:指授权类型,必选,这里填固定值‘code’
client_id:指客户端id,必选,这里填在平台报备时获取的appid
redirect_uri:指重定向URI,可选
scope:指申请的权限范围,可选
state:指客户端当前状态,可选,若填了,则认证服务器会原样返回该值
第⑥步参数:
grant_type:指使用哪种授权模式,必选,这里填固定值‘authorization_code’
code:指从第⑤步获取的code,必选
redirect_uri:指重定向URI,必选,这个值需要和第④步中的redirect_uri保持一致
client_id:指客户端id,必选,这里填在平台报备时获取的appid
client_secret:指客户端密钥,必选,这里填在平台报备时获取的appkey
第⑧步参数:
access_token:指访问令牌,必选,这里填第⑦步获取的access_token
token_type:指令牌类型,必选,大小写不敏感,bearer类型 / mac类型
expires_in:指过期时间,单位秒,当其他地方已设置过期时间,此处可省略该参数
refresh_token:指更新令牌,可选,用即将过期token换取新token
scope:指权限范围,可选,第④步中若已申请过某权限,此处可省略该参数
我们在上面的第八步中会有refresh_token的参数,这个在实际操作中也比较常见
有时候我们在自己的项目中,将登陆和授权设计成类似OAuth2的过程,不过去掉Authorization code。登陆成功返回access_token,然后客户端再请求时,带上access_token。
我们常常会说到TCP/IP,那到底是什么呢。这就需要讲到网络分层模型。TCP在传输层,IP在网络层。那为什么需要分层?因为网络不稳定,导致需要重传的问题。为了提高传输效率我们就需要分块,在传输层中就会进行分块。TCP还有两个重要的内容就是三次握手,四次分手。
HTTPS 协议是由 HTTP 加上TLS/SSL协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护
1客户端通过发送Client Hello报文开始SSL通信。报文中包含客户端支持的SSL的指定版本、加密组件列表(所使用的加密算法及密钥长度),客户端随机数,hash算法。
2服务器可进行SSL通信时,会以Server Hello报文作为应答。和客户端一样,在报文中包含SSL版本以及加密组件,服务端随机数。服务器的加密组件内容是从接收到客户端加密组件内筛选出来的。
3之后服务器发送Certificate报文。报文中包含公开密钥证书。一般实际有三层证书嵌套,其实像下面图二直接用根证书机构签名也是可以的,但是一般根证书机构比较忙,需要类似中介的证书机构来帮助。
4最后服务器发送Server Hello Done报文通知客户端,最初阶段的SSL握手协商部分结束。
5SSL第一次握手结束后,客户端以Client Key Exchange报文作为回应。报文中包含通信加密中使用的一种被称为Pre-master secret的随机密码串。该报文已用步骤3中的公开密钥进行加密。
6接着客户端继续发送Change Cipher Spec报文。该报文会提示服务器,在此报文之后的通信会采用Pre-master secret密钥加密。
7客户端发送Finished报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密报文作为判定标准。
8服务器同样发送Change Cipher Spec报文。
9服务器同样发送Finished报文。
10服务器和客户端的Finished报文交换完毕之后,SSL连接就算建立完成。当然,通信会受到SSL的保护。从此处开始进行应用层协议的通信,即发送HTTP响应。
11应用层协议通信,即发送HTTP响应。
12最后由客户端断开连接。断开连接时,发送close_notify报文。这步之后再发送TCP FIN报文来关闭与TCP的通信。
利用客户端随机数,服务端随机数,per-master secret随机数生成master secret,再生成客户端加密密钥,服务端加密密钥,客户端MAC secert,服务端MAC secert。MAC secert用于做报文摘要,这样能够查知报文是否遭到篡改,从而保护报文的完整性。
Android网络请求知识(一)HTTP基础概念
Android网络请求知识(二)对称和非对称加密、数字签名,Hash,Base64编码
Android网络请求知识(三)授权,TCP/IP,HTTPS建立过程
相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助。
1、TCP连接
要想明白Socket连接,先要明白TCP连接。手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。
建立起一个TCP连接需要经过“三次握手”:
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)
2、HTTP连接
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
1)在HTTP 10中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
2)在HTTP 11中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的做法是即使不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。
3、SOCKET原理
31套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
32 建立socket连接
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
4、SOCKET连接与TCP连接
创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
5、Socket连接与HTTP连接
由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。
0条评论