精华内容
下载资源
问答
  • 计算机网络通讯协议关系图(中文珍藏版),来源地址:http://www.52im.net/thread-180-1-1.html,感谢分享。
  • 网络通讯协议关系图(中文珍藏版)高清矢量图 网络通讯协议关系图(中文珍藏版)高清矢量图
  • UDP网络通讯

    2017-12-13 17:15:36
    UDP网络通讯!UDP网络通讯!UDP网络通讯!UDP网络通讯!UDP网络通讯!UDP网络通讯!UDP网络通讯!UDP网络通讯!UDP网络通讯
  • C# socket网络通讯示例程序,示例代码中一个是服务端,另一个客户端。本示例是学习socket通讯技术入门的最好示例。
  • 用C++编写的基于TCP/IP的Modbus网络通讯工具源码,据参考价值。
  • 网络游戏-网络通讯架构、网络通讯系统以及网络通讯方法.zip
  • VB2010网络通讯实例

    热门讨论 2013-02-20 14:35:55
    VB2010网络通讯实例,含服务器和客户端
  • vc++tcp网络通讯服务器+客户端(附源码)

    万次阅读 多人点赞 2020-10-03 11:25:46
    VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第22章:VC++tcp网络通讯服务器+客户端(附源码) 源代码demo已上传到百度网盘:永久生效 ,代码实现了TCP服务端功能,以及TCP客户端功能 本代码实现大小数据...

      VC++开发常用功能一系列文章 (欢迎订阅,持续更新...)

    第22章:VC++tcp网络通讯服务器+客户端(附源码)

     

    源代码demo已上传到百度网盘:永久生效  ,代码实现了TCP服务端功能,以及TCP客户端功能

    本代码实现大小数据传输都没问题,实现应用于局域网音视频传输,一点问题都没有!

    封装的是CAsyncSocket , 有详细注释,绝对可用,绝对开放源码!

    来直接上代码:

    #pragma once
    namespace TSock 
    {
        typedef void (*TSockCB)(LPCSTR szId, BYTE* pData, int nLen); 

        // 服务器端函数

        // 初始化socket服务器
        extern "C" BOOL PASCAL TSInit(int nPort);

        // 退出socket服务器
        exte

    展开全文
  • 非常漂亮的网络调试助手服务端和客户端及网络通讯帮助类源码
  • Android开发之网络通讯详解

    万次阅读 多人点赞 2016-03-16 21:36:26
    ②Android中网络通讯实现的原理和步骤 ③基于Http协议的访问网络的实例 ④基于Socket套接字的服务器和Android客户端交互的一个实例 ⑤GET请求和POST请求的区别 ⑥Socket与HTTP区别 一、HTTP...

    真正的才智是刚毅的志向。 —— 拿破仑

    目前的App如果没有使用到网络技术,仅仅依靠本地是很难提升自己App的用户量的,21世纪是互联网时代,网络技术已经融入并改变了我们的生活。想象一下假如一周没有网络供你使用,你是不是有跟这个世界脱节了的感觉,哈哈,没有错,网络是如此的重要,因此我们就需要花点时间好好学习下这门技术。如有谬误,欢迎批评指正,如有疑问欢迎留言


    通过本篇博客你将学到以下知识点:

    ①HTTP网络请求的方式

    ②Android中网络通讯实现的原理和步骤

    ③基于Http协议的访问网络的实例

    ④基于Socket套接字的服务器和Android客户端交互的一个实例

    ⑤GET请求和POST请求的区别

    ⑥Socket与HTTP区别


    一、HTTP网络请求的方式

       在Android中发送HTTP网络请求一般有三种方式HttpURLConnectoin、HttpClient、AndroidHttpClient(很少用)。其中AndroidHttpClient这种方式很少使用。接下来我们就来分别学习下这三种HTTP协议的网络请求。

    1.1 HttpURLConnection

        java.net.*提供与联网有关的类,包括流和数据包套接字、Internet协议、常见HTTP处理,通过HttpURLConnection(继承自URLConnection),可用于向指定网站发送GET请求、POST请求。

    HttpURLConnection访问网络的主要步骤:

    首先需要创建一个URL对象,并传入目标的网络地址这样就得到了一个URL对象,得到此对象后调用URL的openConnection();方法即可得到HttpURLConnection对象,与之对应的代码如下:

    URL url=new URL("http://www.baidu.com");
    httpUrlConnection = (HttpURLConnection) url.openConnection();
    

    得到了HttpURLConnection的实例后,可以设置HTTP请求所使用的方法,在上面我们也提到主要有两个,GET和POST。GET表示希望从服务器那里获取数据,而POST则表示希望提交数据给服务器。首先来看下GET方法请求网络的操作,设置请求方式为GET的代码如下:

    httpUrlConnection.setRequestMethod("GET");

    然后可以针对自己的业务需求去定制符合这个需求的代码,比如设置连接超时、读取超时的毫秒数、设置允许输出流,即允许上传数据到web服务、设置允许输入流,即允许下载、设置是否允许使用缓存等等。代码如下:

    httpUrlConnection = (HttpURLConnection) url.openConnection();
    httpUrlConnection.setRequestMethod("GET"); //设置请求方法
    httpUrlConnection.setConnectTimeout(8000); //设置链接超时的时间
    //将读超时设置为指定的超时值,以毫秒为单位。用一个非零值指定在建立到资源的连接后从input流读入时的超时时间。
    //如果在数据可读取之前超时期满,则会引发一个 java.net.sockettimeoutexception。超时时间为零表示无穷大超时。
    httpUrlConnection.setReadTimeout(8000);
    httpUrlConnection.setDoInput(true); //允许输入流,即允许下载
    httpUrlConnection.setDoOutput(true); //允许输出流,即允许上传
    httpUrlConnection.setUseCaches(false); //设置是否使用缓存
    

    设置好这些之后,就可以调用相应的方法从服务器获得它返回的"流"了,这个返回的“流”中就包含了我们所想要的信息,所调用的方法就是getInputStream(),我们可以这样写代码

    InputStream inputStream =httpUrlConnection.getInputStream();
    这样就得到了服务器给我返回的这个“流”,我们就可以从这个“流”中来读取数据了,在操作完后大家不要忘记在最后调用disconnect()这个方法将这个HTTP链接关闭掉。再了解了这些理论知识后,接着我们一起来完成一个案例,相信通过这个案例会加深你对HttpURLConnection的了解。
    首先来看一下这个案例的运行效果,效果图如下:
     

     
    这个界面的布局如下

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width= "match_parent"
        android:layout_height= "match_parent"
        android:orientation="vertical" >
       
        <Button
            android:id= "@+id/btn_send_request"
            android:layout_width= "match_parent"
            android:layout_height= "wrap_content"
            android:text="请求网络" />
    
        <ScrollView
            android:layout_width= "match_parent"
            android:layout_height= "match_parent" >
           
         <TextView
            android:id= "@+id/tv_show_content"
                android:layout_width= "wrap_content"
                android:layout_height= "wrap_content" />
        </ScrollView >
    
    </LinearLayout>
    

    接着来看看MainActivity的代码

    package com.example.httpcommunicatepractice;
    
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    
    import android.support.v7.app.ActionBarActivity;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    
    
    public class MainActivity extends ActionBarActivity implements OnClickListener {
         
         private Button btnSendRequest;
         private TextView tvShowContent;
         private static final String httpUrl="http://www.imooc.com/api/teacher?type=4&num=40" ;
         public static final int SHOW_RESPONSE = 0;
    
         private Handler handler= new Handler(){
                public void handleMessage(Message msg) {
                     switch (msg. what) {
                     case SHOW_RESPONSE:
                         String result=(String) msg. obj;
                          tvShowContent.setText(result);
                          break;
                    }
               };
         };
         
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout. activity_main);
           
            btnSendRequest=(Button) findViewById(R.id.btn_send_request );
            tvShowContent=(TextView) findViewById(R.id.tv_show_content );
           
            btnSendRequest.setOnClickListener( this);
           
        }
       
        @Override
         public void onClick(View v) {
         if(v.getId()==R.id. btn_send_request){
               httpUrlConnection_get();
         }
         }
    
         private void httpUrlConnection_get() {
                new Thread( new Runnable() {
                    
                     @Override
                     public void run() {
                         
                         InputStreamReader in= null;
                         HttpURLConnection httpUrlConnection= null;
                          try {
                               
                              URL url= new URL("http://www.baidu.com" );
                              httpUrlConnection = (HttpURLConnection) url.openConnection();
                              httpUrlConnection.setRequestMethod( "GET"); //设置请求方法
                              httpUrlConnection.setConnectTimeout(8000); //设置链接超时的时间
                              //将读超时设置为指定的超时值,以毫秒为单位。用一个非零值指定在建立到资源的连接后从input流读入时的超时时间。
                              //如果在数据可读取之前超时期满,则会引发一个 java.net.sockettimeoutexception。超时时间为零表示无穷大超时。
                              httpUrlConnection.setReadTimeout(8000);
                              httpUrlConnection.setDoInput( true); //允许输入流,即允许下载
                              httpUrlConnection.setDoOutput( true); //允许输出流,即允许上传
                              httpUrlConnection.setUseCaches( false); //设置是否使用缓存
                                //建立连接,上面对urlConn的所有配置必须要在connect之前完,这里需要注意的是
                                //connect这个方法,在getInputStream()方法中会隐式的被调用,所以这里不写也没有问题
                               httpUrlConnection.connect();
                               InputStream inputStream=httpUrlConnection.getInputStream();
                               in= new InputStreamReader(inputStream);
                               BufferedReader bf= new BufferedReader(in);
                               StringBuffer sb= new StringBuffer();
                               String inputLine= null;
                               
                               while((inputLine=bf.readLine())!= null){
                                    sb.append(inputLine);
                               }
                               
                               Message message= new Message();
                               message. what= SHOW_RESPONSE;
                               message. obj=sb.toString();
                                handler.sendMessage(message);
                               
                         } catch (Exception e) {
                               e.printStackTrace();
                         } finally{
                                if(httpUrlConnection!= null){
                                    httpUrlConnection.disconnect();
                               }
                         }
                    }
               }).start();
               
         }
    
    }
    

    从代码中可以看到当点击“请求网络”这个按钮的时候,首先会去调用httpUrlConnection_get()这个方法,在这个方法中回去开启一个子线程去访问网络,这里我们访问的是百度首页,通过httpUrlConnection.getInputStream()这个方法获取百度给我们返回过来的"流",然后通过BufferedReader去读取这个流并将读取的结果放进StringBuffer中,通过Handler、Message的形式发送个主线程,更新TextView的内容。
    在这里要注意三点:
    ①不要忘了添加访问网路的权限

    <uses-permission android:name= "android.permission.INTERNET" />

    ②更新控件的操作必须要放到主线程中,不能在子线程中更新控件
    ③可能看完后会有人问,一般我们在真正的开发中都是带有参数的,这里我提供了一个连接在上述MainActivity中大家可以看到有这么一行代码

    private static final String httpUrl ="http://www.imooc.com/api/teacher?type=4&num=40" ;

    这个连接是慕课网的一个连接,大家可以把上述的"http://www.baidu.com",直接换成httpUrl,然后运行,可以发现它返回了相应的json。这里我这样做的主要目的就是要告诉大家,这个方式请求的参数是直接加载链接后面的。
    那么如果是想要提交数据给服务器应该怎么办呢?其实也不复杂,只需要将HTTP 请求的方法改成POST,并在获取输入流之前把要提交的数据写出即可。注意每条数据都要以键值对的形式存在,数据与数据之间用&符号隔开,比如说我们想要向服务器提交用户名和密码,就可以这样写:

    httpUrlConnection.setRequestMethod( "POST");//设置请求方法
    DataOutputStream dataOutputStream=new DataOutputStream(urlConnection.getOutputStream());
     //要提交的参数 
    String content = "username=admin&password=123456";
    //将要上传的内容写入流中 
    dataOutputStream.writeBytes(content);  
    //刷新、关闭 
    dataOutputStream.flush(); 
    dataOutputStream.close();
    

    关于HttpURLConnection的post请求大家可以找个自己公司的POST请求的接口,或者找一个POST请求的网站,自己去试试。我这里就不做演示了


    1.2 HttpClient

         HttpClient是Apache提供的HTTP网络访问接口,从一开始的时候就被引入到了AndroidAPI中。它可以完成和HttpURLConnection几乎一模一样的效果,但是和HttpURLConnection不同的是HttpClient是org.apache.*下提供的类两者之间的用法也是有很大的差别的,HttpClient与HttpURLConnection一样也同样有GET和POS请求两种方式,同HttpURLConnection一样首先我们来学习一下HttpClient访问网络的主要步骤:
    首先我们应该清楚HtppClient是一个接口,因此无法创建它的实例,通常情况下我们都会创建一个Apache提供给我们的一个默认的实例,代码如下:

    //取得HttpClient对象
    HttpClient httpClient= new DefaultHttpClient();
    

    假如我们想发送一条GET请求,我们需要创建一个HttpGet对象,将要访问的目标网络的地址传递过去,然后调用HttpClient的execute()方法并将HttpGet对象传入即可,与之对应的代码如下:

    //HttpGet连接对象
    HttpGet httpGet= new HttpGet("http://www.baiduc.com" );
    //请求HttpClient,取得HttpResponse
    HttpResponse httpResponse=httpClient.execute(httpGet);
    

    假如我们想发送一条POST请求,我们需要创建一个HttpPost请求,将要访问的目标网络的地址传递过去,代码如下:

    HttpPost httpPost=new HttpPost( "http://www.baidu.com" );

    与GET方法不同的是,POST请求需要NameValuePair集合来存放待提交的参数,并将这个参数传到UrlEncodedFormEntity中,然后调用HttpPost的setEntity()方法将构建好的UrlEncodedFormEntity设置进去,与之对应的代码如下:

    List<NameValuePair> params=new ArrayList<NameValuePair>();
    params.add( new BasicNameValuePair("username" ,"admin" ));
    params.add( new BasicNameValuePair("password" ,"123456" ));
    HttpEntity httpEntity = new UrlEncodedFormEntity(params, "utf-8");
    httpPost.setEntity(httpEntity);
    

    接下来的操作就与GET方法类似了,调用HttpClient的execute()方法,并将HttpPost对象传入即可,代码如下:

    HttpResponse httpResponse = httpClient.execute(httpPost);

    从上面我们可以看到它返回了一个HttpResponse对象,服务器返回的所有信息都包含在了这个对象中,通常我们的做法是先取得服务器返回的状态码,如果返回的状态码为200就说明请求和响应都成功了,此时我们就可以按照业务需求去进行相应的代码的书写了,与之对应的代码如下:

    if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
        //访问网络成功   
    }
    

    访问网络成功之后,可能有的同学会说,怎样拿到服务器给返回的数据呢?其实Apache已经给我们提供好方法了,我们可以调用HttpResponse这个类的getEntity()方法来获取一个HttpEntity对象,然后在调用EntityUtils.toString()这个方法将HttpEntity对象转换成字符串就可以了,与之对应的代码如下:

    HttpEntity entity = httpResponse.getEntity();
    String strResult = EntityUtils.toString(entity,"utf-8");
    

    可以看到在转换成字符串时,我们还可以指定相应的编码,防止转换后出现乱码的情况,至此HttpClient访问网络的内容就讨论的差不多了,接着来一个案例,这个案例HttpURLConnection的GET方法一样,只不过这里我们采用的是HttpClient的GET方法,因此我们只要稍作修改即可,修改过后的代码如下:

    public class MainActivity extends ActionBarActivity implements OnClickListener {
         
       。。。。。。。。。
        @Override
         public void onClick(View v) {
                switch (v.getId()) {
                case R.id. btn_send_request:
                    httpClient_get();
                     break;
               }
         }
       
    
         private void httpClient_get() {
               
                new Thread( new Runnable() {
                    
                     @Override
                     public void run() {
                         
                          try {
                                //HttpGet连接对象
                               HttpGet httpGet= new HttpGet("http://www.baidu.com" );
                                //取得HttpClient对象
                               HttpClient httpClient= new DefaultHttpClient();
                                //请求HttpClient,取得HttpResponse
                               HttpResponse httpResponse=httpClient.execute(httpGet);
                               if(httpResponse.getStatusLine().getStatusCode()==HttpStatus. SC_OK){
                                     //取得返回的字符串
                                     resultData=EntityUtils. toString(httpResponse.getEntity(),"utf-8");
                                    Message message= new Message();
                                    message. what= SHOW_RESPONSE;
                                    message. obj= resultData;
                                     handler.sendMessage(message);
                               }
                         } catch (Exception e) {
                               e.printStackTrace();
                         }
                         
                    }
               }).start();
               
         }
         
    }
    

    这与刚开始的运行效果是一样的。如果有参数对于GET请求直接加在链接后面就行了,你也可以跟HttpURLConnection一样试试访问这个链接"http://www.imooc.com/api/teacher?type=4&num=40";它的POST请求大家可以自己试验一下。


    1.3 Android.net.*(Android网络接口)

    常常使用此包下的类进行Android特有的网络编程,如:访问WiFi,访问Android联网信息,邮件等功能。


    1.4 GET和POST请求方式的区别

     Get和Post提交的区别
     ①get提交,提交的信息都显示在地址栏中。post提交,提交的信息不显示在地址栏中
     ②get提交,对于敏感的数据信息不安全。post提交,对于敏感信息安全。
     ③get提交,对于大数据不行,因为地址栏存储体积有限post提交,可以提交大体积数据
     ④get提交,将信息封装到了请求消息的请求行中post提交,将消息封装到了请求体中

     在服务器的一个区别:
     如果出现将中文提交到tomcat服务器,服务器默认会用iso8859-1进行解码此时会出现乱码,通过iso8859-1进行编码,在用指定的中文码表解码,即可。这种方式get提交和post提交都有效,但是对于post提交方式提交的中文,还有另一种解决办法,就是直接使用服务端一个对象,request对象的setCharacterEncoding方法直接设置指定的中文码表就可以将中文数据解析出来。这个方法只对请求体中的数据进行解码。


    1.5 HttpURLConnection和HttpClient应该使用哪种方式?

         目前网上的一些比较好的开源项目它们的网络请求基本都是基于HttpURLConnection或者HttpClient的,比如:Volley的Http请求在 android 2.3 版本之前是通过HttpClient ,在之后的版本是通过URLHttpConnection。xUtils都是通过HttpClient请求网(bitmap模块图片下载是通过URLHttpConnection),以及我们经常用的Universal-Image-Loader是采用HttpURLConnection等。URLHttpConnection默认支持GZIP压缩,api操作简单。那么究竟是选择HttpURLConnection呢?还是选择HttpClient呢?大家可以参考郭霖的这篇博客:http://blog.csdn.net/guolin_blog/article/details/12452307这里我只将他最后的总结的话跟大家分享下,如果你想详细的学习,就点击连接,最后的总结:

    在Android 2.2版本之前,HttpClient拥有较少的bug,因此使用它是最好的选择。

    而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择。它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。对于新的应用程序应该更加偏向于使用HttpURLConnection,因为在以后的工作当中我们也会将更多的时间放在优化HttpURLConnection上面。


    二、Socket(套接字)


    2.1 简介及分类
        Socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
    应用程序与服务器通信可以采用两种模式:TCP可靠通信 和UDP不可靠通信。


    2.2 建立Socket链接
    首先来看一点理论知识:
    套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。


    服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。


    客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。


    连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。


    接着我们来看一张来自于百度百科的TCP通讯模型


    从图中我们可以看出要想建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务端称为ServerSocket。在建立服务端(ServerSocket)时需要使用ServertSocket对象,这个对象会自动对其构造函数中传入的端口号进行监听,并在接收到连接请求后,使用ServerSocket.accept()方法返回一个连接的Socket对象。而不管是建立客户端还是在进行其他数据交换方面的操作时,都需要使用Socket类,Socket类在进行初始化时需要传入Server端的Ip地址和端口号,代码如下:

    Server socket = new Socket(HOST, PORT);   //host:为服务器的IP地址  port:为服务器的端口号
    并返回连接到Server端的一个Socket对象,如果是连接失败,那么将返回异常,同ServerSocket,它也是自动进行连接请求的。如果你的配置也就是服务器的Ip地址以及端口号配置好的话,这个连接就已经建立好了,但是仅仅是建立连接还没有用,进行数据的交互才是我们最终的目的,此时就需要用到IO流中的OutputStream和InputStream了,这一点从图中也可以看到,主要有两种情况:
    当应用程序需要对流进行数据写操作时,可以使用Socket.getOutputStream()方法返回的数据流进行操作。
    当应用程序要从流中取出数据时,可以使用Socket.getInputStream()方法返回的数据流进行操作。我们可以这样操

    InputStream inputStream = socket.getInputStream();
    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    

    这样我们就可以从bufferedReader中读取数据了。与之对应的socket.getOutputStream()的操作与之类似。好了说了这么多理论知识,我们来一个小例子
    这个例子要实现的效果的效果图如下:



    从图中可以看出它实现了手机客户端通过Socket与服务器进行通讯这个功能,手机客户端发送给服务器一条消息后,服务器会把这条消息再发给客户端。它是怎么实现的呢?首先来理理思路:
    通过上面的理论知识可以想到我们首要做的就是建立socket连接,这样才能保证客户端和服务端进行通讯,其次在连接建立后再安卓端会向服务端发送一条消息,通过Socket.getOutputStream()这个方法得到输出流,然后然后将这个输出的字符流转化为字节流转化的方法是用OutputStreamWriter然后再通过BufferWriter这个类的对象将要发送的这个消息内容通过write()方法写进去,通过调用BufferWriter.flush()或close()方法后,将其发送到服务器端。它的示例代码为:

    BufferedWriter  mWriter = new BufferedWriter( new OutputStreamWriter(mSocket.getOutputStream(),"utf-8" ));
    mWriter.write("你想向服务器端发送的内容"+“\n” );
    mWriter.flush();
    

    而服务器端通过

    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8" ));
    通过这个方法就可以得到客户端向服务器发送过来的消息。
     
    首先来看下服务端的代码
    package com.beijing.edu;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class MySocketServer {
    
         private static final int SOCKET_PORT = 1234;
         private ServerSocket serverSocket = null;
         private boolean flag = true;
         private BufferedReader reader;
         private BufferedWriter writer;
    
         /**
          * @param args
          */
         public static void main(String[] args) {
               MySocketServer socketServer = new MySocketServer();
               socketServer.initSocket();
         }
    
         private void initSocket() {
                try {
                     serverSocket = new ServerSocket( SOCKET_PORT);
                    System. out.println( "服务已经启动,端口号:" + SOCKET_PORT);
                     while ( flag) {
                         Socket clientSocket = serverSocket.accept();
                         System. out.println( "有客户端连接" );
    
                         SocketThread socketThread = new SocketThread(clientSocket);
                         socketThread.start();
    
                    }
    
               } catch (IOException e) {
                    e.printStackTrace();
               } finally {
                     try {
                          writer.close();
                    } catch (IOException e) {
                         e.printStackTrace();
                    }
               }
         }
    
         public class SocketThread extends Thread {
    
                private Socket socket;
    
                public SocketThread(Socket clientSocket) {
                     this. socket = clientSocket;
               }
    
                @Override
                public void run() {
                     super.run();
    
                    InputStream inputStream;
                     try {
                          //获取输入流
                         inputStream = socket.getInputStream();
                          //得到读取BufferedReader对象
                          reader = new BufferedReader( new InputStreamReader(inputStream,"utf-8" ));
                          writer = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(),"utf-8" ));
                          //循环读取客户端发过来的消息
                          while ( flag) {
                                if ( reader.ready()) {
                                    String result= reader.readLine();
                                    System. out.println( "客户端发过来的消息为:" + result);
                                     //将服务端发过来的消息,发送给客户端
                                     writer.write( "服务端发过来的消息:" + result+"\n" );
                                     writer.flush();
                               }
                         }
                    } catch (IOException e) {
                         e.printStackTrace();
                    }
    
               }
         }
    }
    

    其实服务端的代码非常简单,就是开启一个子线程来循环的从客户端那里获取消息,获取消息后将这个消息打印出来,并将这个消息再发送给客户端就,注意这里的服务端的代码我是运行在MyEclipse中的,是一个Java Project,你也可以在Eclipse中建一个Java Project。
    接着来看看Android客户端的代码:

    package com.example.socketclient1;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import android.support.v7.app.ActionBarActivity;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    
    public class MainActivity extends ActionBarActivity implements OnClickListener {
         
         private EditText etIp;
         private EditText etPort;
         private Button btnStart;
         private TextView tvContent;
         private EditText etSendContent;
         private Button btnSendMessage;
         
         private Socket clientSocket;
         private boolean isReceivingMsgReady;
         private BufferedReader mReader;
         private BufferedWriter mWriter;
         private StringBuffer sb= new StringBuffer();
         
         private Handler handler= new Handler(){
               public void handleMessage(android.os.Message msg) {
                   switch (msg. what) {
                   case 0:
                        sb.append((String)msg. obj);
                        tvContent.setText( sb.toString());
                        break;
                  }
              };
         };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout. activity_main);
           
            etIp=(EditText) findViewById(R.id. et_ip);
            etPort=(EditText) findViewById(R.id. et_port);
            btnStart=(Button) findViewById(R.id. btn_start);
            etSendContent=(EditText) findViewById(R.id.et_send_content );
            btnSendMessage=(Button) findViewById(R.id.btn_send );
            tvContent=(TextView) findViewById(R.id.tv_content );
            btnStart.setOnClickListener( this);
            btnSendMessage.setOnClickListener( this);
           
        }
    
         @Override
         public void onClick(View v) {
               switch (v.getId()) {
              
               case R.id. btn_start:
                   if(! isReceivingMsgReady){
                       initSocket();
                  }
                   break;
               case R.id. btn_send:
                  send();
                   break;
              }
         }
    
         private void send() {
    
               new AsyncTask<String, Integer, String>() {
    
                   @Override
                   protected String doInBackground(String... params) {
                       sendMsg();
                        return null;
                  }
    
              }.execute();
         
         }
    
         /**
          * 向服务器发送消息
          */
         protected void sendMsg() {
               try {
                  String msg=etSendContent.getText().toString();
                   //通过BufferedWriter对象向服务器写数据
                   mWriter.write(msg+ "\n");
                   //一定要调用flush将缓存中的数据写到服务器
                   mWriter.flush();
                  String str= "\n"+ "我:" +msg+"   "+getTime(System.currentTimeMillis ())+"\n" ;
                    handler.obtainMessage(0,str).sendToTarget();
              } catch (IOException e) {
                  e.printStackTrace();
              }
         }
    
         private void initSocket() {
              
               new Thread( new Runnable() {
                  
                   @Override
                   public void run() {
                       String ip= etIp.getText().toString();
                        int port=Integer.parseInt(etPort.getText().toString());
                       
                        try {
                             isReceivingMsgReady= true;
                             //在子线程中初始化Socket对象
                             clientSocket= new Socket(ip,port);
                             //根据clientSocket.getInputStream得到BufferedReader对象,从而从输入流中获取数据
                             mReader= new BufferedReader( new InputStreamReader(clientSocket.getInputStream(),"utf-8" ));
                             //根据clientSocket.getOutputStream得到BufferedWriter对象,从而从输出流中获取数据
                             mWriter= new BufferedWriter( new OutputStreamWriter(clientSocket.getOutputStream(),"utf-8" ));
                             while( isReceivingMsgReady){
                                  if( mReader.ready()){
                                       handler.obtainMessage(0, mReader.readLine()).sendToTarget();
                                 }
                                 Thread. sleep(200);
                            }
                             mWriter.close();
                             mReader.close();
                             clientSocket.close();
                       } catch (Exception e) {
                            e.printStackTrace();
                       }
                  }
              }).start();
              
         }
         
         /**
          * 得到自己定义的时间格式的样式
          * @param millTime
          * @return
          */
         private String getTime( long millTime) {
              Date d = new Date(millTime);
              SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" );
              System. out.println(sdf.format(d));
               return sdf.format(d);
         }
    }

    可以看到服务器的代码和客户端的代码都很简单,这样就通过Socket实现了 客户端和服务器的通信。大家可以动手试试,在这里需要提醒大家注意的是:
    ①千万不要忘了添加权限。

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    ② Java socket编程时,常使用BufferedReader的readLine()函数来进行数据的读取。但是该函数是阻塞的,如果在接收的数据中不含有'\n','\r'或者结束符时,往往导致进程挂起,从而程序无法继续。所以在发送数据的另一端,一定要记得在最后加换行符,这一点在客户端的体现是mWriter.write(msg+ "\n");这一行代码,后面要加“\n”。


    三、Socket与HTTP通讯的区别

               通常情况下Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。而HTTP连接使用的是“请求—响应”的方式,也就是说当需要数据的时候想服务器发送一条请求,服务器收到请求后返回相应的数据,请求过后这个连接就不在了,当下次需要数据时再发送请求,综上:HTTP这种方式连接不是一直存在的,而Socket一旦建立连接,这个连接是一直存在的,直到双方断开连接,这个连接才会消失。

             很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端需要定时向服务器端发送连接请求,这种在客户端的请求方式叫做“轮询”,顾名思义定时的去询问服务器是否有新数据,当服务器有新数据时,此时收到客户端发送的请求就会把这个数据发送给客户端,当服务器再有新消息时就要等到下次客户端的请求了。

             在开发中如果对数据的即时性要求比较高的情况下一般采用Socket通讯,例如聊天的功能。如果对数据的即时性要求不是特别高的情况下一般采用HTTP通讯, 比如在项目中,我们请求的接口,请求一次就给我们返回数据,很少会去不断的去请求服务器的数据。


    关于Socket的讲解本节讲解了其理论知识,在下一节将会给大家带来利用Socket实现两个Android手机端的通讯,谢谢大家持续关注。

    如有谬误,欢迎批评指正,如有疑问欢迎留言,大家一起讨论,共同进步。

     


    源码猛戳这里。。。








    
    展开全文
  • 用VC2010编写的基于TCPIP的Modbus网络通讯工具源码
  • Unity如何实现网络通讯(一):HTTP

    千次阅读 2017-10-12 09:45:12
    网络通讯一般有强联网和弱联网,强联网我们一般使用TCP或者UDP,弱联网则是最常用的HTTP。今天我们首先来说一说HTTP。 超文本传输协议(HTTP,HyperText Transfer Protocol)是当前最广泛的网络协议,这里不讲述HTTP...
     
    
    网络通讯一般有强联网和弱联网,强联网我们一般使用TCP或者UDP,弱联网则是最常用的HTTP。今天我们首先来说一说HTTP。
    超文本传输协议(HTTP,HyperText Transfer Protocol)是当前最广泛的网络协议,这里不讲述HTTP的发展和底层,我们直奔主题,看HTTP如何访问和使用。
    首先我们要做的就是有一个服务器,就是一个网站,我们可以通过visual Studio来建立网站,如图:
    然后添加webApi来导入模板,如下图操作:
    点击确定然后生成我们的模板,我们会看到在右边的解决方案视图能看到许多已经建好的文件夹和文件,这是WebAPI帮助我们生成的,然后我们可以点击运行看是否可以运行,如果可以运行,说明我们建的网站可以使用,然后我们可以再初始界面上看见一个类,里面是我们通过修改网站路径可以获取到的值,如下图:
    这样,我们就可以在浏览器看到我们在vs中的值。我们会发现返回的值是Get方法中的字符串数组,如果我们想要获取有参方法中的值,就需要通过Get方法输入参数来访问:只需要在原有路径后加上 '?id=2'就可以访问了(不包含引号)。
    接下来就是发布网站了,我们可以再右侧找到自己的网站点击右键点击发布:
    如果之前没有配置文件可以点击下拉菜单->新建,然后创建自己的配置文件,名称自己定,然后点击连接,把发布方法改为“文件系统”,路径建议放在图中位置,记得在wwwroot下再创建一个文件夹,否则生成的文件会散布在wwwroot文件中,和其他网站文件发生混乱。
    然后点击设置,将配置改为Release,然后点击发布。注意:如果发布失败,可能是因为权限问题,我们可以使用管理员身份打开vs然后再次发布便可以成功。
    当网站发布成功,我们便可以使用微软为我们提供的IIS来对网站进行部署:
    如果是win10系统,直接在cortona中输入IIS就可以打开,不同系统IIS的位置可以自己查询,打开IIS后,我们开始新建网站:
    点击网站然后新建,会弹出一个界面,设置自己的网站名称,物理路径选择之前我们发布的路径,然后修改端口号,因为默认的80端口已经被占用,我们可以自己设定一个端口号,0-65535均可,然后点击确定。生成后我们可以点击右侧浏览来测试网站是否建立成功。
    如果我们的网站建立失败,很有可能是因为IIS的一些服务没有开启,这个可以再网上查询,开启相应服务便可以使用。

    接下来我们可以再Unity中去请求了:
    首先说一下Get请求:
    我们可以通过www类去请求HTTP,URL就是我们的网站地址,需要说的一点是HTTP是必须发出请求后才可以从服务器上获取资源,所以我们每需要一次,就需要请求一次,也可以一次把资源全部请求,但一般不会这样做。
    然后就是开启协程,等待请求完毕,然后接受返回的信息:
      private void GetURL( string URL)
        {
            WWW data = new WWW (URL);
            StartCoroutine(Request(data));
        }
    然后说一下Post请求:
    Post请求会多一个WWWForm类,通过AddField方法来添加参数,相当于Get方法路径后的“?id=3”,
    private void PostURL( string URL, int id)
        {
            //定义一个表单
            WWWForm form = new WWWForm ();
            //给表单添加值
            form.AddField( "id" , 3);
            WWW data = new WWW (URL, form);
            StartCoroutine(Request(data));
        }
    最后实现协程的具体逻辑:
    private IEnumerator Request( WWW data)
        {
            yield return data;
            if ( string .IsNullOrEmpty(data.error))
            {
               Debug.Log(data.text);
            }
            else
            {
                 Debug.LogError(data.error);
            }
        }
    这样,如果没有错误的情况下,我们会返回text文本信息,使我们请求的值,如果返回的是一个类,则我们收到的是一个json串,我们可以通过LitJson插件进行解Json来解析数据。
    最后说一下Get方式和Post方式的差别,使用Get方式效率要高,但是安全性会降低,Post方式则相反,所以使用哪种方式我们要根据实际情况来判断。
    展开全文
  • 嵌入式网络通讯详解

    千次阅读 2017-02-24 17:45:26
    前言 最近在做网络相关的项目,然而大学学的网络编程以及网络协议相关的知识都已经忘得差不多了。庆幸的是网上牛人多,百度一下发现了一篇言简意赅的文章...

    前言

      最近在做网络相关的项目,然而大学学的网络编程以及网络协议相关的知识都已经忘得差不多了。庆幸的是网上牛人多,百度一下发现了一篇言简意赅的文章(http://www.cnblogs.com/feitian629/archive/2012/11/16/2774065.html),唤醒了我许多大学的回忆,不胜感慨。我下定决心要把网络的相关知识从新梳理一遍,希望可以更上一层楼,打算从这里开始,因而将这篇文章记录如下。

    ISO参考模型

      ISO/OSI的参考模型共有7层,由低层至高层分别为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。各层功能分别为:
      (1)物理层:在物理媒体上传输原始的数据比特流。
      (2)数据链路层:将数据分成一个个数据帧,以数据帧为单位传输。有应有答,遇错重发。
      (3)网络层:将数据分成一定长度的分组,将分组穿过通信子网,从信源选择路径后传到信宿。
      (4)传输层:提供不具体网络的高效、经济、透明的端到端数据传输服务。
      (5)会话层:进程间的对话也称为会话,会话层管理不同主机上各进程间的对话。
      (6)表示层: 为应用层进程提供格式化的表示和转换数据服务。
      (7)应用层:提供应用程序访问OSI环境的手段。

    TCP/IP协议模型

      TCP/IP 网络协议栈分为应用层(Application)、传输层(Transport)、网络层(Network)和链路层(Link)四层。通信过程中,每层协议都要加上一个数据首部(header),称为封装(Encapsulation),如下图所示:
      这里写图片描述
      不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理。
      网络层的IP 协议是构成Internet 的基础。IP 协议不保证传输的可靠性,数据包在传输过程中可能丢失,可靠性可以在上层协议或应用程序中提供支持。
      传输层可选择TCP 或UDP 协议。TCP 是一种面向连接的、可靠的协议,有点像打电话,双方拿起电话互通身份之后就建立了连接,然后说话就行了,这边说的话那边保证听得到,并且是按说话的顺序听到的,说完话挂机断开连接。也就是说TCP 传输的双方需要首先建立连接,之后由TCP 协议保证数据收发的可靠性,丢失的数据包自动重发,上层应用程序收到的总是可靠的数据流,通讯之后关闭连接。UDP 协议不面向连接,也不保证可靠性,有点像寄信,写好信放到邮筒里,既不能保证信件在邮递过程中不会丢失,也不能保证信件是按顺序寄到目的地的。使用UDP 协议的应用程序需要自己完成丢包重发、消息排序等工作。
      其实在链路层之下还有物理层,指的是电信号的传递方式,比如现在以太网通用的网线(双绞线)、早期以太网采用的的同轴电缆(现在主要用于有线电视)、光纤等都属于物理层的概念。

    常用网络设备工作原理

    (1)集线器
      集线器(Hub)是工作在物理层的网络设备,用于双绞线的连接和信号中继(将已衰减的信号再次放大使之传得更远)。
    (2)交换机
      交换机是工作在链路层的网络设备,可以在不同的链路层网络之间转发数据帧(比如十兆以太网和百兆以太网之间、以太网和令牌环网之间),由于不同链路层的帧格式不同,交换机要将进来的数据包拆掉链路层首部重新封装之后再转发。
    (3)路由器
      路由器是工作在第三层的网络设备,同时兼有交换机的功能,可以在不同的链路层接口之间转发数据包,因此路由器需要将进来的数据包拆掉网络层和链路层两层首部并重新封装。

    网络数据的流程

      数据传输经过的各层协议过程如下:
    这里写图片描述
      以太网驱动程序首先根据以太网首部中的“协议类型”字段确定该数据帧是IP、ARP 还是RARP 协议的数据报,然后交给相应的协议处理。假如是IP 数据报,IP 协议再根据IP 首部中的“上层协议”字段确定该数据报是TCP、UDP、ICMP 还是IGMP,然后交给相应的协议处理。假如是TCP 段或UDP段,TCP 或UDP 协议再根据TCP 首部或UDP 首部的“端口号”字段确定应该将应用层数据交给哪个用户进程。IP 地址是标识网络中不同主机的地址,而端口号就是同一台主机上标识不同进程的地址,IP 地址和端口号合起来标识网络中唯一的进程。
      虽然IP、ARP 和RARP 数据报都需要以太网驱动程序来封装成帧,但是从功能上划分,ARP 和RARP 属于链路层,IP 属于网络层。虽然ICMP、IGMP、TCP、UDP 的数据都需要IP 协议来封装成数据报,但是从功能上划分,ICMP、IGMP 与IP 同属于网络层,TCP 和UDP属于传输层。

    以太网帧格式

    这里写图片描述
    (1)其中的源地址和目的地址是指网卡的硬件地址(也叫MAC 地址),长度是48 位,是在网卡出厂时固化的。
    (2)注意网卡芯片(例如DM9000A)收到的数据就是如上所示的一长串数据;其中包括以太网帧头、IP报报头、传输层协议段头、应用层所需数据。
    (3)以太网帧中的数据长度规定最小46 字节,最大1500 字节,ARP 和RARP 数据包的长度不够46 字节,要在后面补填充位。最大值1500 称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU,如果一个数据包从以太网路由到拨号链路上,数据包度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation)。ifconfig 命令的输出中也有“MTU:1500”。注意,MTU 这个概念指数据帧中有效载荷的最大长度,不包括帧首部的长度。

    IP数据包格式

    这里写图片描述
      IP 数据报的首部长度和数据长度都是可变长的,但总是4 字节的整数倍。对于IPv4,4 位版本字段是4。4 位首部长度的数值是以4 字节为单位的,最小值为5,也就是说首部长度最小是4x5=20 字节,也就是不带任何选项的IP 首部,4 位能表示的最大值是15,也就是说首部长度最大是60 字节。8 位TOS 字段有3 个位用来指定IP 数据报的优先级(目前已经废弃不用),还有4 个位表示可选的服务类型(最小延迟、最大呑吐量、最大可靠性、最小成本),还有一个位总是0。总长度是整个数据报(包括IP 首部和IP 层payload)的字节数。每传一个IP 数据报,16 位的标识加1,可用于分片和重新组装数据报。3 位标志和13 位片偏移用于分片。TTL(Time to live)是这样用的:源主机为数据包设定一个生存时间,比如64,每过一个路由器就把该值减1,如果减到0 就表示路由已经太长了仍然找不到目的主机的网络,就丢弃该包,因此这个生存时间的单位不是秒,而是跳(hop)。协议字段指示上层协议是TCP、UDP、ICMP 还是IGMP。然后是校验和,只校验IP 首部,数据的校验由更高层协议负责。IPv4的IP 地址长度为32 位。

    UDP段格式

    这里写图片描述

    TCP段格式

    这里写图片描述

    序号:指出段中的数据部分在发送方数据流中的位置。

    确认号:指出接收方希望收到对方下次发送的数据的第一个字节的序号。

    TCP段首部的定长部分为20个字节,即5个单位的长度。

    URG位:紧急标志,和紧急指针配合使用,当其为1时表示,此报文要尽快传送。

    ACK位:确认标志,和确认号字段配合使用,当ACK位置1时,确认号字段有效。

    PSH位:为推送标志,置1时,发送方将立即发送缓冲区中的数据。

    RST位:复位标志,置1时,表明有严重差错,必须释放连接。

    SYN位: 同步标志,置1时,表示请求建立连接。

    FIN位:终止标志,置1时,表明数据已经发送完,请求释放连接。

    窗口大小:32bit,用于向对方通告当前本机的接受缓冲区的大小。

    校验和字段长度:16bit,校验范围包括段首部、数据以及伪首部。

    TCP数据传输过程

      建立连接的过程是三次握手,而关闭连接通常需要4 个段(四次挥手),服务器的应答和关闭连接请求通常不合并在一个段中,因为有连接半关闭的情况,这种情况下客户端关闭连接之后就不能再发送数据给服务器了,但是服务器还可以发送数据给客户端,直到服务器也关闭连接为止。
    这里写图片描述
    (1)TCP连接的建立

      【1】. 客户端发出段1,SYN 位表示连接请求。序号是1000,这个序号在网络通讯中用作临时的地址,每发一个数据字节,这个序号要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包的情况,另外,规定SYN 位和FIN 位也要占一个序号,这次虽然没发数据,但是由于发了SYN 位,因此下次再发送应该用序号1001。mss表示最大段尺寸,如果一个段太大,封装成帧后超过了链路层的最大帧长度,就必须在IP 层分片,为了避免这种情况,客户端声明自己的最大段尺寸,建议服务器端发来的段不要超过这个长度。

      【2】 服务器发出段2,也带有SYN 位,同时置ACK 位表示确认,确认序号是1001,表示“我接收到序号1000 及其以前所有的段,请你下次发送序号为1001 的段”,也就是应答了客户端的连接请求,同时也给客户端发出一个连接请求,同时声明最大尺寸为1024。

      【3】 客户端发出段3,对服务器的连接请求进行应答,确认序号是8001。在这个过程中,客户端和服务器分别给对方发了连接请求,也应答了对方的连接请求,其中服务器的请求和应答在一个段中发出,因此一共有三个段用于建立连接,称为”’三方握手(three-way-handshake)”’。在建立连接的同时,双方协商了一些信息,例如双方发送序号的初始值、最大段尺寸等。

    (2)TCP数据传输过程

      【1】 客户端发出段4,包含从序号1001 开始的20 个字节数据。

      【2】 服务器发出段5,确认序号为1021,对序号为1001-1020 的数据表示确认收到,同时请求发送序号1021 开始的数据,服务器在应答的同时也向客户端发送从序号8001 开始的10 个字节数据,这称为piggyback。

      【3】 客户端发出段6,对服务器发来的序号为8001-8010 的数据表示确认收到,请求发送序号8011 开始的数据。在数据传输过程中,ACK 和确认序号是非常重要的,应用程序交给TCP 协议发送的数据会暂存在TCP 层的发送缓冲区中,发出数据包给对方之后,只有收到对方应答的ACK 段才知道该数据包确实发到了对方,可以从发送缓冲区中释放掉了,如果因为网络故障丢失了数据包或者丢失了对方发回的ACK 段,经过等待超时后TCP 协议自动将发送缓冲区中的数据包重发。

    (5)TCP连接的关闭

      【1】 客户端发出段7,FIN 位表示关闭连接的请求。

      【2】 服务器发出段8,应答客户端的关闭连接请求。

      【3】 服务器发出段9,其中也包含FIN 位,向客户端发送关闭连接请求。

      【4】 客户端发出段10,应答服务器的关闭连接请求。

    展开全文
  • Linux 网络通讯命令 查看端口命令

    千次阅读 2018-12-27 11:05:27
    Linux netstat命令用于显示网络状态。 利用netstat指令可让你得知整个Linux系统的网络情况。 netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。netstat是在内核...
  • 网络通讯的两种方式

    千次阅读 2018-02-14 10:02:07
    TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据失败,则客户端会自动重发给数据。 2.UDP(用户数据报协议) UDP方式类似于发送短信,使用这种...
  • 老师为你提供一条从0学起到C++架构师的一条奋斗之路,跟住老师1-2年学习,让你在1-2年内成长到别人花费5-10年才能成长到的程度,如果你希望做一个高端大气上档次的C++网络通讯架构师,在不久的将来月薪能拿到30-80K...
  • 完整的网络通讯过程

    千次阅读 2017-09-30 23:41:23
    交换机的作用是将将所有电脑连接在同一个网段内,那么该网段内的电脑就可以实现相互通讯 A电脑 IP:192.168.1.1 B电脑 IP:192.168.1.2 假如A电脑想要PING通B电脑时,先向交换机发送一个包,里面包含要通讯的IP地址...
  • 达梦数据库登陆时报网络通讯异常的排查方法一、达梦数据库的服务没有启动二、远程访问被防火墙拦截三、端口号不对四、达到最大会话数限制,无法建立新的连接 在大家刚刚接触达梦数据库的时候,经常会碰到的一个问题...
  • VISUAL C++ 网络通讯编程案例精选VISUAL C++ 网络通讯编程案例精选VISUAL C++ 网络通讯编程案例精选VISUAL C++ 网络通讯编程案例精选
  • TCP网络通讯传送文件

    2010-07-13 13:16:45
    TCP网络通讯传送文件 TCP网络通讯传送文件 TCP网络通讯传送文件 TCP网络通讯传送文件 TCP网络通讯传送文件
  • tcp/ip网络通讯安全加密方法

    千次阅读 2018-04-06 08:35:21
    tcp/ip网络通讯安全是一个广受关注的话题,现在也有一些基于tcp/ip加密技术标准如SSL,TLS等。但很多时候编写一些简单的网络通讯把这标准加密应用添加进来乎一下子把程序变得复杂了,而实现自己的加密算法那就更加不...
  • 基于移动网络通讯行为的风险用户识别 比赛地址:基于移动网络通讯行为的风险用户识别,该比赛是联通大数据公司发起的,同时作为我们的实训的比赛。下面是自己参加比赛过程的报告: 第一次参加这种比赛,...
  • LINK - 服务器间网络通讯错误

    千次阅读 2016-12-09 01:21:13
    解决:LINK - 服务器间网络通讯错误 分2种情况: 1:MSSQL数据库服务端,首先确定你的服务端的用户名、数据库帐号、数据库密码、数据库端口、是否正确; 路径1:/root/authd/etc/table.xml 里面找到下面...
  • VB.NET 网络通讯示例(服务端)

    千次阅读 2015-08-12 17:03:29
    VB.NET 网络通讯示例(服务端)
  • VB.NET 网络通讯示例(客户端)

    千次阅读 2015-08-12 17:07:20
    VB.NET 网络通讯示例(客户端)
  • 游戏开发中网络通讯协议对比

    万次阅读 2017-01-18 19:10:29
    网络游戏开发中,通讯协议是一个无法被避免的问题,无论对于客户端开发中还是服务器开发程序猿而言,制定一个合适的通讯协议是很有必要的 游戏联网需求有弱联网游戏,即时互动类游戏 选择通讯协议的时候主要关注于...
  • 如何基于TCP/IP协议进行MFC Socket网络通讯编程

    万次阅读 多人点赞 2017-03-09 14:06:50
    MFC Socket简单网络通讯编程
  • 网络通讯,实现,原理

    2011-05-31 22:51:17
    网络通讯,实现技术,查找原理网络通讯,实现技术,查找原理网络通讯,实现技术,查找原理网络通讯,实现技术,查找原理网络通讯,实现技术,查找原理网络通讯,实现技术,查找原理网络通讯,实现技术,查找原理网络...
  • labview 网络通讯 TCP

    千次阅读 2019-06-06 09:24:00
    1)目标:Labview图形界面间进行TCP网络通信(Socket),基本流程: 2) 硬件:网线连接 3)IP:配置在同一IP段,Server :10.10.3.43 , Client:10.10.3.x(不是43) 4)labview TCP通信控件子选板 5)服务器...
  • 本文将介绍基于Socket网络通讯的服务器端和客户端的程序设计。 一、服务器端的程序设计  关于Socket服务器端的内容,在这里只提供设计思路,以及相应的测试界面,不提供具体的代码。系列一中有提到,Socket服务器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 397,039
精华内容 158,815
关键字:

网络通讯