发送_发送器 - CSDN
  • JAVA发送手机短信,流传有几种方法:(1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册;(2)使用短信mao的方式进行短信的发送,这种方式应该是比较的常用,前提是需要购买...

    原文地址:http://sms.webchinese.cn/api.shtml

    JAVA发送手机短信,流传有几种方法:(1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册;(2)使用短信mao的方式进行短信的发送,这种方式应该是比较的常用,前提是需要购买硬件设备,呵呵(3)使用中国网建提供的SMS短信平台(申请账号地址:http://sms.webchinese.cn/default.shtml

    本程序主要是运用了中国网建提供的SMS短信平台

    注意:smsText的值要用【】括起来


    重要提示:用接口发送验证码的程序员注意,近期短信验证码轰炸软件泛滥,请在发送验证码的时候,加上一个图形校验码验证,防止机器人读取狂发验证码!!!不明事宜请联系客服咨询。发送手机验证码请做好以下几点防范: 发送验证码1分钟只能点击发送1次; 相同IP手机号码1天最多提交20次; 验证码短信单个手机号码30分钟最多提交10次; 在提交页面加入图形校验码,防止机器人恶意发送; 在发送验证码接口程序中,判断图形校验码输入是否正确; 新用户用接口测试验证码时,请勿输入:测试等无关内容信息,请直接输入:验证码:xxxxxx,发送。 接口发送触发短信时,您可以把短信内容提供给客服绑定短信模板,绑定后24小时即时发送。未绑定模板的短信21点以后提交,隔天才能收到。

    GBK编码发送接口地址
    http://gbk.api.smschinese.cn/?Uid=本站用户名&Key=接口安全秘钥&smsMob=手机号码&smsText=验证码:8888
    UTF-8编码发送接口地址:
    http://utf8.api.smschinese.cn/?Uid=本站用户名&Key=接口安全秘钥&smsMob=手机号码&smsText=验证码:8888
    获取短信数量接口地址(UTF8):
    http://www.smschinese.cn/web_api/SMS/?Action=SMS_Num&Uid=本站用户名&Key=接口安全秘钥
    获取短信数量接口地址(GBK):
    http://www.smschinese.cn/web_api/SMS/GBK/?Action=SMS_Num&Uid=本站用户名&Key=接口安全秘钥

    提示:HTTP调用URL接口时, 参数值必须URL编码后再调用

    参数变量 说明
    Gbk编码Url http://gbk.api.smschinese.cn/
    Utf-8编码Url http://utf8.api.smschinese.cn/
    Uid 本站用户名(如您无本站用户名请先注册)[免费注册]
    Key 注册时填写的接口秘钥(可到用户平台修改接口秘钥)[立刻修改]
    如需要加密参数,请把Key变量名改成KeyMD5,
    KeyMD5=接口秘钥32位MD5加密,大写。
    smsMob 目的手机号码(多个手机号请用半角逗号隔开)
    smsText 短信内容,最多支持400个字,普通短信70个字/条,长短信64个字/条计费

    多个手机号请用半角,隔开
    如:13888888886,13888888887,1388888888 一次最多对100个手机发送
    短信内容支持长短信,最多400字,普通短信70个字/条含签名,长短信64字/条计费

    短信发送后返回值 说 明
    -1 没有该用户账户
    -2 接口密钥不正确 [查看密钥]
    不是账户登陆密码
    -21 MD5接口密钥加密不正确
    -3 短信数量不足
    -11 该用户被禁用
    -14 短信内容出现非法字符
    -4 手机号格式不正确
    -41 手机号码为空
    -42 短信内容为空
    -51 短信签名格式不正确
    接口签名格式为:【签名内容】
    -6 IP限制
    大于0 短信发送数量
    注:调用API接口,请登录平台,申请106网关发送,即发即到!
      发送测试短信请勿输入:短信测试等词语,请直接提交您要发送的短信内容;
      接口发送短信时请在内容后加签名:【XX公司或XX网名称】,否者会被屏蔽。
      短信签名可在用户平台平台上设置,也可以在短信内容后,直接加入。
    ASP程序实例 C#程序示例 JAVA程序示例 PHP程序示例 VB.NET程序实例 VB程序实例

    1. ASP 调用例子
    <%
    '常用函数
    '输入url目标网页地址,返回值getHTTPPage是目标网页的html代码
    function getHTTPPage(url)
    dim Http
    set Http=server.createobject("MSXML2.XMLHTTP")
    Http.open "GET",url,false
    Http.send()
    if Http.readystate<>4 then
    exit function
    end if
    getHTTPPage=bytesToBSTR(Http.responseBody,"GB2312")
    set http=nothing
    if err.number<>0 then err.Clear
    end function
    Function BytesToBstr(body,Cset)
    dim objstream
    set objstream = Server.CreateObject("adodb.stream")
    objstream.Type = 1
    objstream.Mode =3
    objstream.Open
    objstream.Write body
    objstream.Position = 0
    objstream.Type = 2
    objstream.Charset = Cset
    BytesToBstr = objstream.ReadText
    objstream.Close
    set objstream = nothing
    End Function

    '自已组合一下提交的URL加入自己的账号和密码
    sms_url="http://sms.webchinese.cn/web_api/?Uid=账号&Key=接口密钥&smsMob=手机号码&smsText=验证码:8888"
    response.write getHTTPPage(sms_url)
    %>

    2.C# 调用
    //需要用到的命名空间
    using System.Net;
    using System.IO;
    using System.Text;
    //调用时只需要把拼成的URL传给该函数即可。判断返回值即可
    public string GetHtmlFromUrl(string url)
    {
    string strRet = null;

    if(url==null || url.Trim().ToString()=="")
    {
    return strRet;
    }
    string targeturl = url.Trim().ToString();
    try
    {
    HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(targeturl);
    hr.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
    hr.Method = "GET";
    hr.Timeout = 30 * 60 * 1000;
    WebResponse hs = hr.GetResponse();
    Stream sr = hs.GetResponseStream();
    StreamReader ser = new StreamReader(sr, Encoding.Default);
    strRet = ser.ReadToEnd();
    }
    catch (Exception ex)
    {
    strRet = null;
    }
    return strRet;
    }

    3.JAVA调用

    import java.io.UnsupportedEncodingException;
    import org.apache.commons.httpclient.Header;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.NameValuePair;
    import org.apache.commons.httpclient.methods.PostMethod;

    public class SendMsg_webchinese {

    public static void main(String[] args)throws Exception
    {

    HttpClient client = new HttpClient();
    PostMethod post = new PostMethod("http://gbk.api.smschinese.cn");
    post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=gbk");//在头文件中设置转码
    NameValuePair[] data ={ new NameValuePair("Uid", "本站用户名"),new NameValuePair("Key", "接口安全秘钥"),new NameValuePair("smsMob","手机号码"),new NameValuePair("smsText","验证码:8888")};
    post.setRequestBody(data);

    client.executeMethod(post);
    Header[] headers = post.getResponseHeaders();
    int statusCode = post.getStatusCode();
    System.out.println("statusCode:"+statusCode);
    for(Header h : headers)
    {
    System.out.println(h.toString());
    }
    String result = new String(post.getResponseBodyAsString().getBytes("gbk"));
    System.out.println(result); //打印返回消息状态


    post.releaseConnection();

    }

    }

    jar包下载
    commons-logging-1.1.1.jar
    commons-httpclient-3.1.jar
    commons-codec-1.4.jar

    演示程序下载
    java_dome.rar

    说明:如果返回值是200,应该是整段程序代码没有执行完整,只获取到client.executeMethod(post)HTTP状态码的消息;接口是提交成功,没有执行下半部的返回消息代码。
    client.executeMethod(post);HTTP状态码参考:http://baike.baidu.com/view/1790469.htm

    4.PHP
    $url='http://sms.webchinese.cn/web_api/?Uid=账号&Key=接口密钥&smsMob=手机号码&smsText=验证码:8888';

    echo Get($url);
    function Get($url)
    {
    if(function_exists('file_get_contents'))
    {
    $file_contents = file_get_contents($url);
    }
    else
    {
    $ch = curl_init();
    $timeout = 5;
    curl_setopt ($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $file_contents = curl_exec($ch);
    curl_close($ch);
    }
    return $file_contents;
    }

    5.VB.NET
    '调用发送短信,NoList接收号码.多个之间用,分开,Memo内容70字
    Public Function SendSMS(ByVal NoList As String, ByVal Memo As String) As String
    Dim Url As String = "http://sms.webchinese.cn/web_api/?Uid=账号&Key=接口密钥&smsMob=手机号码&smsText=验证码:8888"
    Dim webClient As New Net.WebClient()
    Try
    'Dim responseData As Byte() =
    Dim srcString As String = webClient.DownloadString(Url)
    Return srcString
    Catch
    Return "-444"
    End Try
    End Function

    6.VB
    Public Function getHtmlStr(strUrl As String) '获取远程接口函数
    On Error Resume Next
    Dim XmlHttp As Object, stime, ntime
    Set XmlHttp = CreateObject("Microsoft.XMLHTTP")
    XmlHttp.open "GET", strUrl, True
    XmlHttp.send
    stime = Now '获取当前时间
    While XmlHttp.ReadyState <> 4
    DoEvents
    ntime = Now '获取循环时间
    If DateDiff("s", stime, ntime) > 3 Then getHtmlStr = "": Exit Function
    Wend
    getHtmlStr = StrConv(XmlHttp.responseBody, vbUnicode)
    Set XmlHttp = Nothing
    End Function

    代码使用:在窗体代码相应位置写如下代码
    dim a as string
    a=getHtmlStr("http://sms.webchinese.cn/web_api/?Uid=账号&Key=接口密钥&smsMob=手机号码&smsText=验证码:8888") '获取接口返回值


    展开全文
  • TCP的发送过程由滑动窗口控制,而滑动窗口的大小受限于发送窗口和拥塞窗口,拥塞窗口由拥塞控制算法的代表,而发送窗口是流量控制算法的代表,这篇笔记记录了发送窗口相关的内容,包括发送窗口的初始化、更新、以及...

    TCP的发送过程由滑动窗口控制,而滑动窗口的大小受限于发送窗口和拥塞窗口,拥塞窗口由拥塞控制算法的代表,而发送窗口是流量控制算法的代表,这篇笔记记录了发送窗口相关的内容,包括发送窗口的初始化、更新、以及它是如何影响数据发送过程的。

    1. 概述

    TCP的发送窗口可以用下图表示:
    在这里插入图片描述

    如图所示,TCB中有三个成员和发送窗口强相关。

    struct tcp_sock {
    ...
    	//下一个要发送的序号,即序号等于snd_nxt的数据还没有发送
    	u32	snd_nxt;	/* Next sequence we send		*/
    	//已经发送,但是还没有被确认的最小序号,注意序号等于snd_una的数据已经发送,
    	//最想收到的确认号要大于snd_una。但是有一个特殊情况,如果发送的所有数据都
    	//已经被确认,那么snd_una将等于下一个要发送的数据,即snd_una代表的数据还
    	//没有发送,见下面tcp_ack()更新snd_una就可以理解这一点了
    	u32	snd_una;	/* First byte we want an ack for	*/
    	//发送窗口大小,以字节为单位,来源于输入段首部的窗口字段,即对端接收缓冲区的剩余大小
    	u32	snd_wnd;	/* The window we expect to receive	*/
    	//记录到目前为止对端通告过的窗口的最大值,可以代表对端接收缓冲区的最大值
    	u32	max_window;	/* Maximal window ever seen from peer	*/
    	//写系统调用一旦成功返回,说明数据一被TCP协议接收,这时就要为每一个数据分配一个序号,
    	//write_seq就是下一个要分配的序号,其初始值由secure_tcp_sequence_number()基于
    	//算法生成。注意等于write_seq的序号还没有被分配
    	u32	write_seq;	/* Tail(+1) of data held in tcp send buffer */
    ...
    };
    

    2. snd_una和snd_wnd的更新

    snd_una是发送窗口的左边界,如果该字段更新,即使发送窗口大小snd_wnd没有发生变化,整个发送窗口也会前移,这样从流量控制的角度,就可以发送更多的数据(是否真的可以发送,还要考虑拥塞窗口等其它因素)。

    2.1 初始化

    可以想的到,snd_una的初始化一定发生在第一个数据段发送过程中,而snd_wnd的初始化应该是发生在第一个输入段处理过程中,所以需要客户端和服务器端分开来看。

    2.1.1 客户端初始化

    客户端对snd_una的初始化当然是发生在SYN段的发送过程中,相关代码如下:

    int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
    {
    ...
    	//选择初始发送序号
    	if (!tp->write_seq)
    		tp->write_seq = secure_tcp_sequence_number(inet->saddr,
    							   inet->daddr,
    							   inet->sport,
    							   usin->sin_port);
    ...
    }
    static void tcp_connect_init(struct sock *sk)
    {
    ...
    	//发送窗口大小要从输入段首部的窗口字段获取,这时还没有任何输入段,先初始化为0
    	tp->snd_wnd = 0;
    	//初始化snd_una为第一个序号,该函数之后write_seq将会分配给SYN段
    	tp->snd_una = tp->write_seq;
    ...
    }
    

    对snd_wnd的初始化发生在收到SYN+ACK段时,相关代码如下:

    static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
    					 struct tcphdr *th, unsigned len)
    {
    ...
    	if (th->ack) {
    ...
    		tp->snd_wnd = ntohs(th->window);
    ...
    	}
    }
    

    2.1.2 服务器端初始化

    正面理解的话,服务器端对snd_una的初始化应该是发生在发送SYN+ACK段时,但是实际上不是,而是发生在收到第三次握手的ACK段时。如笔记TCP之服务器端收到ACK包所述,三次握手完成后,创建了子套接字,然后在tcp_child_process()中会继续调用tcp_rcv_state_process()处理ACK报文,代码如下:

    int tcp_child_process(struct sock *parent, struct sock *child,
    		      struct sk_buff *skb)
    {
    	int ret = 0;
    	int state = child->sk_state;
    
    	//如果用户进程没有锁住child,则让child重新处理该ACK报文,这可以让child
    	//套接字由TCP_SYN_RECV迁移到TCP_ESTABLISH状态
    	if (!sock_owned_by_user(child)) {
    		//见下文
    		ret = tcp_rcv_state_process(child, skb, tcp_hdr(skb),
    					    skb->len);
    		/* Wakeup parent, send SIGIO */
    		//child套接字状态发生了迁移,唤醒监听套接字上的进程,可能由于调用accept()而block
    		if (state == TCP_SYN_RECV && child->sk_state != state)
    			parent->sk_data_ready(parent, 0);
    	} else {
    		/* Alas, it is possible again, because we do lookup
    		 * in main socket hash table and lock on listening
    		 * socket does not protect us more.
    		 */
    		 //缓存该skb后续处理
    		sk_add_backlog(child, skb);
    	}
    
    	bh_unlock_sock(child);
    	sock_put(child);
    	return ret;
    }
    
    int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
    			  struct tcphdr *th, unsigned len)
    {
    ...
    	/* step 5: check the ACK field */
    	if (th->ack) {
    		int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH);
    
    		switch (sk->sk_state) {
    		case TCP_SYN_RECV:
    			if (acceptable) {
    ...
    				tcp_set_state(sk, TCP_ESTABLISHED);
    				//用ACK段中的确认号初始化本端的snd_una
    				tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
    				//用输入报文的窗口字段初始化发送窗口大小
    				tp->snd_wnd = ntohs(th->window) <<
    					      tp->rx_opt.snd_wscale;
    ...
    			}
    			break;
    ...
    		}//end of switch()
    	} else
    		goto discard;
    ...
    	return 0;
    }
    

    2.2 传输过程中更新

    显然,数据传输过程中,应该在收到ACK后更新snd_una和snd_wnd。如果输入段中携带了ACK,最终都会有tcp_ack()处理确认相关的内容,相关的代码如下:

    static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
    {
    ...
    	u32 prior_snd_una = tp->snd_una;
    	u32 ack = TCP_SKB_CB(skb)->ack_seq;
    ...
    	if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
    ...
    		//快速路径情况,用ack更新snd_una,由于快速路径,所以通告的窗口大小一定
    		//没有发生变化,所以不需要更新snd_wnd
    		tp->snd_una = ack;
    		flag |= FLAG_WIN_UPDATE;
    ...
    	} else {
    ...
    		//慢速路径下,调用函数更新窗口
    		flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
    ...
    	}
    ...
    }
    
    /* Update our send window.
     *
     * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
     * and in FreeBSD. NetBSD's one is even worse.) is wrong.
     */
    static int tcp_ack_update_window(struct sock *sk, struct sk_buff *skb, u32 ack,
    				 u32 ack_seq)
    {
    	struct tcp_sock *tp = tcp_sk(sk);
    	int flag = 0;
    	u32 nwin = ntohs(tcp_hdr(skb)->window);
    
    	if (likely(!tcp_hdr(skb)->syn))
    		nwin <<= tp->rx_opt.snd_wscale;
    
    	if (tcp_may_update_window(tp, ack, ack_seq, nwin)) {
    		flag |= FLAG_WIN_UPDATE;
    		tcp_update_wl(tp, ack, ack_seq);
    
    		if (tp->snd_wnd != nwin) {
    			//更新发送窗口大小
    			tp->snd_wnd = nwin;
    
    			/* Note, it is the only place, where
    			 * fast path is recovered for sending TCP.
    			 */
    			tp->pred_flags = 0;
    			tcp_fast_path_check(sk);
    			//如果通告的最大接收窗口发生变化,更新max_window
    			if (nwin > tp->max_window) {
    				tp->max_window = nwin;
    				tcp_sync_mss(sk, inet_csk(sk)->icsk_pmtu_cookie);
    			}
    		}
    	}
    	//用ack更新snd_una
    	tp->snd_una = ack;
    
    	return flag;
    }
    

    3. 发送窗口对发送过程的影响

    这里要明白的是,发送窗口是实现流量控制的关键,它影响的只有新数据的发送过程,与重传无关,因为重传的数据一定是在对端接收能力之内。

    TCP之数据发送(二)中有看到新数据发送的两个关键函数tcp_write_xmit()和tcp_push_one(),而且二者非常相似,参考之前的笔记中分析的tcp_snd_wnd_test()和tcp_mss_split_point()就可以明白发送窗口是如何影响发送过程的。

    展开全文
  • UDP本地发送与接收

    2019-01-15 08:53:08
    所使用的内容 *Socket:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字 * * Socket原理机制: 通信的两端都有Socket。...建立发送端,接收端。 建立数据包。 调用Socket的发...

    在这里插入图片描述
    所使用的内容
    本页面所完成的事本机发送与接收
    执行是请先运行接收页面,再进行发送页面

    *Socket:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字
    *
    * Socket原理机制:
    通信的两端都有Socket。
    网络通信其实就是Socket间的通信。
    数据在两个Socket间通过IO传输。
    UDP传输:
    DatagramSocket与DatagramPacket此类表示数据报包
    建立发送端,接收端。
    建立数据包。
    调用Socket的发送接收方法。
    关闭Socket。
    发送端与接收端是两个独立的运行程序。

    	DatagramSocket构造方法摘要:
    			DatagramSocket(int port, InetAddress laddr) 
          						创建数据报套接字,将其绑定到指定的本地地址。
        DatagramSocket常用方法:
        		void send(DatagramPacket p) 
          						从此套接字发送数据报包。 
          		void receive(DatagramPacket p) 
          						从此套接字接收数据报包。 
        DatagramPacket构造方法摘要:
          		DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
          						构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。					
          		DatagramPacket(byte[] buf, int length) 
          						构造 DatagramPacket,用来接收长度为 length 的数据包。**
    
    public static void main(String[] args) throws Exception {
    		//端口
    		int port=10008;
    		//发送者ip地址
    		InetAddress ia=InetAddress.getLocalHost();	//创建Socket对象
    		DatagramSocket ds=new DatagramSocket(port);
    		//创建发送数据
    		String s="晚安";
    		byte[] buf=s.getBytes();
    		//创建数据包
    		DatagramPacket dp=new DatagramPacket(buf, buf.length,ia,10001);//10001接收方端口
    		
    		//发送数据
    		ds.send(dp);
    		
    		//发送结束后结束
    		ds.close();
    
    	}
    	//这是发送端
    
    
    

    //接收端

    public static void main(String[] args) throws Exception {
    		//接收端端口
    		int port=10001;
    		//ip地址
    //		InetAddress ia=InetAddress.getByName("192.4.2.5");
    		//创建Socket接收对象
    		DatagramSocket ds=new DatagramSocket(port);
    		System.out.println("接收者打开...........");
    		
    		//接收对象
    		byte[] buf=new byte[1024];
    		DatagramPacket dp=new DatagramPacket(buf, buf.length);
    		ds.receive(dp);
             
    		//将接收到的解码
    	    //获取ip
    		String senip=dp.getAddress().toString();
    		//获取端口
    		int senport=dp.getPort();
    		//将接受到数组转换成字符串
    		byte[] bs=dp.getData();
    		String message=new String(bs);
    		System.out.println("接收到"+senip+"发送的"+message);
    		
    		//关闭Socket
    		ds.close();
    	}
    
    展开全文
  • 一道经典的面试题是从URL在浏览器被输入到页面展现的过程中发生了什么?大多数回答都是请求响应之后DOM是怎么被构建、被绘制出来。 ... 要搞懂这个问题,我们需要先解决下面五个问题: ...什么情...

    一道经典的面试题是从URL在浏览器被输入到页面展现的过程中发生了什么?大多数回答都是请求响应之后DOM是怎么被构建、被绘制出来。

    但是你有没想过,收到的HTML如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的?

    要搞懂这个问题,我们需要先解决下面五个问题:

    • 现代浏览器在与服务器建立了一个TCP连接后,是否会在一个HTTP请求完成之后断开?什么情况下会断开?
    • 一个TCP连接可以对应几个HTTP请求?
    • 一个TCP连接中,HTTP请求发送可以一起发送吗(比如一起发起三个请求,再三个响应一起接收)?
    • 为什么有的时候刷新页面不需要重新建立SSL连接?
    • 浏览器对同一Host建立TCP连接的数量有没限制?

    现代浏览器在与服务器建立了一个TCP连接后是否会在一个HTTP请求完成后断开?什么情况下会断开?

    HTTP/1.0中,一个服务器在发送完一个HTTP响应后,会断开TCP连接。但是这样每次请求都会重新建立和断开TCP连接,代价过大。所以虽然标准中没有设定,某些服务器对Connection: keep-aliveHeader进行了支持。

    意思是说,完成这个HTTP请求之后,不要断开HTTP请求使用TCP连接。这样的好处是连接可以被重新使用,之后发送HTTP请求的时候不需要重新建立TCP连接,以及如果维持连接,那么SSL的开销也可以避免。

    以下两张图片是短时间内访问某站点的时间统计:
    图片描述

    头一次访问,有初始化连接和SSL开销

    图片描述

    初始化连接和SSL开销消失了,说明使用的是同一个TCP连接

    持久连接: 既然维持TCP连接好处这么多,HTTP/1.1就把Connection头写进标准,并且默认开启持久化连接(除非请求中声明Connection: close),那么浏览器和服务器之间是会维持一段时间的TCP连接,不会一个请求结束就断掉。

    所以第一个问题的答案是: 默认情况下建立TCP连接不会断开,只有在请求报头中声明Connection: close才会请求完成之后关闭连接。

    一个TCP连接可以对应几个HTTP请求?

    了解第一个问题之后,其实这个问题也有了答案,如果维持连接,一个TCP连接可以发送多个HTTP请求的

    一个TCP连接中,HTTP请求可以一起发送吗?

    HTTP/1.1存在一个问题,单个TCP连接在同一时刻只能处理一个请求,意思是说: 两个请求的声明周期不能重叠,任意两个HTTP请求从开始到结束的时间在同一个TCP连接里不能重叠。

    虽然 HTTP/1.1 规范中规定了 Pipelining 来试图解决这个问题,但是这个功能在浏览器中默认是关闭的。

    先来看一下 Pipelining 是什么,RFC 2616 中规定了:一个支持持久连接的客户端可以在一个连接中发送多个请求(不需要等待任意请求的响应)。收到请求的服务器必须按照请求收到的顺序发送响应

    至于标准为什么这么设定,我们可以大概推测一个原因:由于 HTTP/1.1 是个文本协议,同时返回的内容也并不能区分对应于哪个发送的请求,所以顺序必须维持一致

    比如你向服务器发送了两个请求 GET /query?q=A 和 GET /query?q=B,服务器返回了两个结果,浏览器是没有办法根据响应结果来判断响应对应于哪一个请求的(因为TCP都是绑定到一个网络端口的,笔者注!!)

    Pipelining 这种设想看起来比较美好,但是在实践中会出现许多问题:

    • 有些代理服务器不能正确的处理 HTTP Pipelining
    • 正确的流水线实现是复杂的。
    • Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。

    所以现代浏览器默认是不开启 HTTP Pipelining 的。

    但是,HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求。至于 Multiplexing 具体怎么实现的就是另一个问题了。我们可以看一下使用 HTTP2 的效果。
    图片描述

    绿色是发起请求到请求返回的等待时间,蓝色是响应的下载时间,可以看到都是在同一个 Connection,并行完成的。

    所以这个问题也有了答案:在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP请求可以在同一个 TCP 连接中并行进行。

    那么在 HTTP/1.1 时代,浏览器是如何提高页面加载效率的呢?主要有下面两点:

    • 维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。
    • 和服务器建立多个 TCP 连接。

    为什么有的时候刷新页面不需要重新建立 SSL 连接?

    在第一个问题的讨论中已经有答案了,TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的。

    浏览器对同一 Host 建立 TCP 连接到数量有没有限制?

    假设我们还处在 HTTP/1.1 时代,那个时候没有多路传输,当浏览器拿到一个有几十张图片的网页该怎么办呢?

    肯定不能只开一个TCP连接顺序下载,那样用户肯定等的很难受,但是如果每个图片都开一个 TCP 连接发 HTTP 请求,那电脑或者服务器都可能受不了,要是有 1000 张图片的话总不能开 1000 个TCP连接吧,你的电脑同意 NAT 也不一定会同意。

    所以答案是:有。Chrome最多允许对同一个Host建立六个TCP连接。不同的浏览器有一些区别。

    那么回到最开始的问题,HTML如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?

    如果图片都是HTTPS连接并且在同一个域名下,那么浏览器在SSL握手之后会和服务器商量能不能用HTTP2,如果能的话就使用Multiplexing功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个TCP连接去获取,但是可以确定的是 Multiplexing很可能会被用到。

    如果发现用不了HTTP2呢?或者用不了HTTPS(现实中的HTTP2都是在HTTPS上实现的,所以也就是只能使用HTTP/1.1)。

    那浏览器就会在一个HOST上建立多个TCP连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了。

    展开全文
  • 当应用程序希望通过TCP与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP将在两个应用程序之间建立一个全双工(full-duplex)的通信。 这个全双工的通信将...
  • 1.实现短信的发送功能 在学习的视频里面发现了这个发送短信的功能实现 就好奇写了一个小demo 先看一下页面的效果吧 很简单的布局 两个输入框 一个按钮 看一下具体的实现效果emmmm 模拟器上看不出来效果 骚等.....
  • Java实现邮件发送

    2019-08-22 14:05:18
    Java实现邮件发送 一、邮件服务器与传输协议 要在网络上实现邮件功能,必须要有专门的邮件服务器。这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱...
  • Java邮件发送详解

    2019-08-13 09:06:30
    电子邮件 要在网络上实现邮件功能,必须要有专门的邮件服务器。 这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。 ... 电子邮箱(E-Mail地址)的获得...
  • 现在一般很少有用Android原生app发送邮件的需求,但是前段时间公司项目需要在Android app 内部发送邮件,于是就在网上收集资料并整理了一个Demo。虽然最后这个需求被减掉了,但是我这里还是把Demo的内容给大家分享...
  • Shell发送邮件+附件

    2019-05-23 16:39:19
    shell发送邮件+附件log文件 这里以QQ邮箱为发送方进行操作的 1. 生成QQ邮箱授权码 2. 服务器配置 2.1 关闭sendmail的服务 service sendmail status 如果有安装,就关闭sendmail的服务,并关闭开机自启动 ...
  • 本文链接: ... ...但这些应用不可能和我们自己平时发邮件一样,先打开浏览器,登录邮箱,创建邮件再发送。本文将简单介绍如何通过 Java 代码来创建电子邮件,并连接邮件服务器发...
  • 之前一直在做邮件系统,涉及到邮件发送(直发、代发)、邮件下载(国内、国外)、服务商配置、代理(主要针对国外)、日志收集、消息通知、分布式锁、水平拆分等功能, 由于涉及公司隐私问题,在这里提供发邮件和下载...
  • 很多网友程序中都要配置邮箱的,可以让系统自动发送信息。大家可以去http://qdcysm.cn.gongchang.com/去注册试试,发送邮件地址为 W E B@ A B O Y.C N 下面是各个邮件提供商的信息: 邮件自动群发通内部已经内置了...
  • 服务器的处理能力有限,如果单位时间内一条客户端连接发送的消息包过于频繁,那么消息的发送机制本身设计得就不合理。 首先这种情况会造成的服务器压力: 假设同时连接服务器的连接数共有10000条,每条连接以间隔1...
  • 有个朋友问我一个问题,说自己在本地通过smtp发送邮件是可以,但是发布到服务器上无法发送。 我就想到了,是不是部署到阿里云服务器了,安全组有没有开放,如果不开放安全组,那是不可能发送成功的,他说也开放了,...
  • 一、 使用SMTP模块发送邮寄 二、 发送HTML格式右键 三、发送带附件的邮件 四、Django处理邮件的发送 4-1 settings配置 4-2 授权码的获取  4-3 视图函数 4-4 群发邮件(一次发送多份) 4-5 携带附件或发送...
  • 网络产品推广和新闻消息推送时,经常用到的工具就是用客户邮箱发送邮件了,如果是要发送的邮件量非常大的话,一般的建议是搭建自己的邮局服务器,或者是花钱购买专业的邮件群发服务,免费邮箱的SMTP适合少量的邮件...
  • 这两天研究了FFmpeg发送流媒体的命令,在此简单记录一下以作备忘。1. UDP1.1. 发送H.264裸流至组播地址(注:组播地址指的范围是224.0.0.0—239.255.255.255)。下面命令实现了发送H.264裸流“chunwan.h264”至地址...
  • 今天闲来无事,在微博上看到一个关于用java实现的一个发送手机短信的程序,看了看,写的不太相信,闲的没事,把他整理下来,以后可能用得着 JAVA发送手机短信,流传有几种方法:(1)使用webservice接口发送手机短信,这...
  • 支持脚本化自动发送邮件,并且可以带附件。 Mail 简介 HTTP 函数允许您从脚本中直接发送电子邮件。要使邮件函数可用,PHP 需要已安装且正在运行的邮件系统。要使用的程序是由 php.ini 文件中的配置设置定义的。 ...
1 2 3 4 5 ... 20
收藏数 2,804,353
精华内容 1,121,741
关键字:

发送