欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

网络编程

程序员文章站 2024-02-29 20:42:52
...

概述

计算机网络:
是指将地理位置不同的具有独立功能的多台计算机及外部设备,通过通信线路链接起来,在网络操作系统,网络管理软件及网络通讯协议,的管理和协调下,实现资源共享和信息传递的计算机系统

网络编程:
是指就是用来实现,不同计算机上运行的程序间可以进行数据交换

网络模型
计算机间用那种规则进行通信,就是网络模型研究的问题,网络模型一般指
网络编程

网络七层概述

1.物理层: 主要定义物理设备的标准,如网线的接口类型,各种传输介质的传输率,他的主要作用是传输比特流,(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。

2. 数据链路层:主要将从物理层接收到的数据,进行MAC地址(网卡的地址)的封装和解封装,长把这一层的数据叫做帧,这一层工作的设备叫做交换机,数据通过交换机进行传输

3. 网络层: 主要将从下层接收的数据,进行IP地址的封装和解封装,在这一层工作的设备叫做路由器,长把这一层的数据叫做数据包

4. 传输层: 定义了一些传输数据的协议和端口号。如 TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求较高的,数据量大的数据) UDP(用户数据报协议,与TCP协议恰恰相反,用于传输可靠性要求不高,数据量小的数据),主要是从下层接收到的数据,进行分段和传输,到达目的地址后,在进行重组,常常把这一层的数据叫做段

5.会话层: 通过传输层(端口号:传输端口和接收端口)建立数据传输的通道,主要在你的系统之间发起会话或者接收会话(设备之间需要互相认识,可以通过ip也可以是MAC或者是主机名)

6.表示层: 主要是对接收的数据进行解释,加密与解密,压缩和解压缩,等(也就是吧计算机能看懂的东西,转换成人能够看懂的东西)

7.应用层: 主要是一些终端应用,比如 QQ,浏览器这类的(可以把它理解成我们在电脑屏幕上看到的东西,就是终端应用)

网络编程

网络编程三要素

发送信件我们需要有三点,才能保证发送信件的成功
1 收件人地址 (ip)
2 收件人(端口)
3 信的内容,双方都可以看懂(协议)

IP

1.IP:计算机在互联网上的唯一地址;
        192.168.0.100:四段0--255的数据组成(IPv4):点分十进制
        IP地址的范围:
        最小IP地址:000.000.000.000:
        最大IP地址:255.255.255.255:
    A:所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,
     每个IP地址长32bit,比特换算成字节,就是4个字节。
     例如一个采用二进制形式的IP地址是“11000000101010000000000101100100”,
     这么长的地址,人们处理起来也太费劲了。
     为了方便人们的使用,IP地址经常被写成十进制的形式,中间使用符号“.”分开不同的字节。
     于是,上面的IP地址可以表示为“10.0.0.1”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比10容易记忆得多。

    B:IP地址的组成
    IP地址 = 网络号码+主机地址

    A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码:192.168.0.100192是网络号码
    B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码
    C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码

    以下三个IP地址:
    1).192.168.0.100;
    2).192.168.0.200;
    3).192.168.1.100;
    请问以上三个IP地址哪些可以互相访问?关键取决于"子网掩码":
    如果子网掩码:255.255.255.0
              11111111.11111111.11111111.00000000(子网掩码中,全部是1端被标识为"网络号码")
                               此时:1)和2)可以互相访问;
    如果子网掩码:255.255.0.0
              11111111.11111111.00000000.00000000
                此时:1)和2)和3)都可以互访;

    特殊地址:
    127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1   

    DOS命令 ipconfig:查看本机IP地址

    xxx.xxx.xxx.0 网络地址
    xxx.xxx.xxx.255 广播地址

    A类  1.0.0.1---127.255.255.254   (1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)                           (2)127.X.X.X是保留地址,用做循环测试用的。
    B类  128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
    C类  192.0.0.1---223.255.255.254 192.168.X.X是私有地址
    D类  224.0.0.1---239.255.255.254     
    E类  240.0.0.1---247.255.255.254 

端口

1).物理端口:网卡口;
        2).逻辑端口:
            1>.由操作系统维护的;
            2>.Windows的逻辑端口范围:0--65535
            3>.其中0--1024一般由系统内部使用,我们尽量不要使用;
            4>.一个网络应用程序,至少要占用一个端口,可以同时占用多个端口;
              一个端口,在同一时刻,只能由一个应用程序占用;

网络编程
协议

3.协议:TCP,UDP,FTP,HTTP....
        1).UDP协议:
            1.数据打包发送;
            2.数据包大小有限制,最大64K;
            3.面向无连接的(发送信息时,可以没有接收端);
                 所以不安全的;
            类似于:电视信号、广播信号;
        2).TCP协议:
            1.数据流发送数据;
            2.数据大小无限制;
            3.面向连接的(发送信息时,必须要有接收方)
            类似于:打电话;
            三次握手确保链接的建立:1 客户端 请求链接
                                2 服务端 确定授予
                                3 客户端 收到

InetAddress

  java.net.InetAddress(类):
  IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的。
  成员方法:
  静态方法:
    获取任意主机:static InetAddress getByName(String pcName):
    获取自己主机: static InetAddress getLocalHost();
  普通方法:
    主机名:getHostName
    主机Ip地址:getHostAddress
InetAddress localHost = InetAddress.getLocalHost();
Log.d("mmm", localHost.getHostName() + "/" + localHost.getHostAddress());

看下Log

09-04 10:41:07.902 11774-11867/com.example.jh.rxhapp D/mmm: localhost/127.0.0.1

Socket

两台计算机如何通信

Socket套接字:
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
Socket原理机制:
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。

网络编程

UDP发送数据

public class UdpClient extends Thread {
    /*
     * UDP的发送端:
     *
     * 1.实例化一个DatagramSocket对象;
     * 2.准备数据:
     *      1).目标IP--InetAddress对象
     *      2).目标端口;
     *      3).信息内容--byte[]数组
     * 3.实例化一个数据包对象:DatagramPacket对象
     * 4.调用DatagramSocket对象的方法,将数据包发送出去;
     */

    @Override
    public void run() {
        //实例化一个DatagramSocket对象
        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket();
        } catch (SocketException e) {
            e.printStackTrace();
            Log.d("mmm", "服务器连接失败");
        }
        //准备数据
        InetAddress ip = null;
        try {
            ip = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            Log.d("mmm", "未找到服务器");
        }
        int port = 8888;
        byte[] bytes = "UDP发送的数据,请接收".getBytes();
        //实例化DatagramPacket对象
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, ip, port);
        //发送数据
        try {
            datagramSocket.send(datagramPacket);
        } catch (IOException e) {
            e.printStackTrace();
            Log.d("mmm", "消息发送失败");
        }
        //释放资源
        datagramSocket.close();

        Log.d("mmm", "发送完毕");

    }
}
public class UdpServer extends Thread {
    /*
     * 接收端:
     *
     * 1.实例化一个DatagramSocket(端口):
     * 2.准备一个空的byte[]数组,用于接收数据;
     *     准备一个空的数据包对象:DatagramPacket
     * 3.调用DatagramSocket的方法接收数据;
     * 4.从DatagramPacket中解析数据;
     * 5.释放资源
     */

    @Override
    public void run() {

        try {
            //实例化一个DatagramSocket,带端口
            DatagramSocket datagramSocket = new DatagramSocket(8888);
            //创建一个空的byte数组
            byte[] bytes = new byte[1024];
            //准备一个空的DatagramPacket
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
            Log.d("mmm", "服务端启动等待接收数据");
            //接收数据
            datagramSocket.receive(datagramPacket);
            Log.d("mmm", "服务端接收数据完毕");
            //解析数据
            String ip = datagramPacket.getAddress().getHostAddress();
            byte[] data = datagramPacket.getData();
            String s = new String(data, 0, data.length);
            Log.d("mmm", "接收到IP:" + ip + "接收到数据:" + s);

            //释放资源
            datagramSocket.close();

        } catch (Exception e) {
            e.printStackTrace();
            Log.d("mmm", "接收异常");

        }
    }
}
public class UDPActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_udp);
        new UdpServer().start();

        findViewById(R.id.udp_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new UdpClient().start();
            }
        });
    }
}

看下log

09-04 11:56:12.062 14425-14546/com.example.jh.rxhapp D/mmm: 服务端启动等待接收数据
09-04 11:56:13.930 14425-14572/com.example.jh.rxhapp D/mmm: 发送完毕
09-04 11:56:13.930 14425-14546/com.example.jh.rxhapp D/mmm: 服务端接收数据完毕
09-04 11:56:13.930 14425-14546/com.example.jh.rxhapp D/mmm: 接收到IP:127.0.0.1接收到数据:UDP发送的数据,请接收

Tcp基本使用

public class TcpClient extends Thread{
    /*
     * TCP发送端:
     *
     * 1.实例化一个Socket对象,要指定IP和端口;
     * 2.如果要发送数据,通过Socket对象获取输出流:OutputStream
     * 3.输出数据;
     * 4.释放资源:
     */
    @Override
    public void run() {
        try {
            //实例化一个Scoket对象,指定ip和端口
            Socket socket = new Socket("127.0.0.1", 8888);
            //获取发送数据的输出流
            OutputStream outputStream = socket.getOutputStream();
            //输出数据
            outputStream.write("我是TCP发送数据".getBytes());
            //释放资源
            socket.close();
            Log.d("mmm","客户端发送完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
public class TcpServer extends Thread {
    /*
     * TCP接收数据:
     *
     * 1.实例化一个ServerSocket,并指定端口号;
     *   调用ServerSocket的accept()方法等待连接:
     * 2.由于要读取数据,所以通过ServerSocket对象获取"输入流"--InputStream
     * 3.读取信息;
     * 4.释放资源;
     */
    @Override
    public void run() {
        //实例化一个实例化一个ServerSocket,并指定端口
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            //调用serverSocket的accept方法,等待连接
            Log.d("mmm", "等待连接");
            Socket socket = serverSocket.accept();
            Log.d("mmm", "有用户连接");
            //获取输入流读取数据
            InputStream inputStream = socket.getInputStream();
            //读取信息
            byte[] bytes = new byte[1024];
            int len = inputStream.read(bytes);
            String s = new String(bytes, 0, len);
            Log.d("mmm", s);
            //释放资源
            serverSocket.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
调用
public class TCPActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tcp);
        new TcpServer().start();

        findViewById(R.id.tcp_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new TcpClient().start();
            }
        });
    }
}

看下log

09-08 14:32:03.415 6654-6842/com.example.jh.rxhapp D/mmm: 等待连接
09-08 14:32:06.067 6654-6842/com.example.jh.rxhapp D/mmm: 有用户连接
09-08 14:32:06.068 6654-6842/com.example.jh.rxhapp D/mmm: 我是TCP发送数据
09-08 14:32:06.070 6654-6879/com.example.jh.rxhapp D/mmm: 客户端发送完毕

Tcp实现聊天功能


public class TcpChatClient extends Thread {

    private final Handler mHandler;
    private OutputStream mOutputStream;
    private Socket mSocket;

    public TcpChatClient(Handler handler) {
        this.mHandler = handler;
    }

    /*
         * TCP发送端:
         *
         * 1.实例化一个Socket对象,要指定IP和端口;
         * 2.如果要发送数据,通过Socket对象获取输出流:OutputStream
         * 3.输出数据;
         * 4.不断读取数据
         */
    @Override
    public void run() {

        try {
            //实例化一个Socket
            mSocket = new Socket("127.0.0.1", 8888);
            //获取输出流
            mOutputStream = mSocket.getOutputStream();
            //发送消息
            sendMessage("客户端请求链接");
            //获取输入流
            InputStream inputStream = mSocket.getInputStream();
            byte[] bytes = new byte[1024];
            int len = 0;
            //不断的读取数据
            while (true) {
                len = inputStream.read(bytes);
                String msg = new String(bytes, 0, len);
                Message msg1 = new Message();
                msg1.obj = "客户端收到:" + msg;
                mHandler.sendMessage(msg1);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送消息
     *
     * @param message
     */
    public void sendMessage(String message) {
        try {
            mOutputStream.write(message.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void colseSocket() {
        try {
            mSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


public class TcpChatServer extends Thread {

    private final Handler mHanlder;
    private Socket mSocket;
    private OutputStream mOutputStream;

    public TcpChatServer(Handler handler) {
        this.mHanlder = handler;
    }

    /*
            * TCP接收数据:
            *
            * 1.实例化一个ServerSocket,并指定端口号;
            *    调用ServerSocket的accept()方法等待连接:
            * 2.由于要读取数据,所以通过ServerSocket对象获取"输入流"--InputStream
            * 3.读取信息;
            * 4.获取输出流,发送消息
            */
    @Override
    public void run() {
        try {
            //实例化ServerSocket
            ServerSocket serverSocket = new ServerSocket(8888);
            //等待链接
            Log.d("mmm", "服务器等待链接");
            mSocket = serverSocket.accept();
            Log.d("mmm", "链接成功");
            //获取书输入流
            InputStream inputStream = mSocket.getInputStream();
            //获取输出流
            mOutputStream = mSocket.getOutputStream();
            //读取消息
            byte[] bytes = new byte[1024];
            //不断的读取数据
            while (true) {
                int len = inputStream.read(bytes);
                String s = new String(bytes, 0, len);
                Message msg = new Message();
                msg.obj = "服务端收到:"+s;
                mHanlder.sendMessage(msg);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 发送消息
     * @param msg
     */
    public void sendMessage(String msg) {
        try {
            mOutputStream.write(msg.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class TcpChatClientActivity extends AppCompatActivity {

    private TextView mTextView;
    private EditText mEditText;
    private Button mClient;
    private Button mServer;
    private StringBuffer mStringBuffer;


    public Handler handler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            String mssage = (String) msg.obj;
            mStringBuffer.append("\n" + mssage);
            mTextView.setText(mStringBuffer);
        }
    };
    private TcpChatServer mTcpChatServer;
    private TcpChatClient mTcpChatClient;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tcp_chat_client);
        initView();
        mTcpChatServer = new TcpChatServer(handler);
        mTcpChatServer.start();
        mTcpChatClient = new TcpChatClient(handler);
        mTcpChatClient.start();
    }

    private void initView() {
        mTextView = (TextView) findViewById(R.id.tcp_chat_text);
        mEditText = (EditText) findViewById(R.id.tcp_chat_edit);
        mClient = (Button) findViewById(R.id.tcp_chat_button);
        mServer = (Button) findViewById(R.id.tcp_chat_button1);
        mStringBuffer = new StringBuffer();
        mClient.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String trim = mEditText.getText().toString().trim();
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        mTcpChatClient.sendMessage(trim);
                    }
                };
                mEditText.setText("");
                Thread thread = new Thread(runnable);
                if (thread.isAlive()) {
                    thread.run();
                } else {
                    thread.start();
                }

                hideSoftInput();
            }
        });
        mServer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String trim = mEditText.getText().toString().trim();
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        mTcpChatServer.sendMessage(trim);
                    }
                };
                mEditText.setText("");
                Thread thread = new Thread(runnable);
                if (thread.isAlive()) {
                    thread.run();
                } else {
                    thread.start();
                }

                hideSoftInput();
            }
        });
    }

    public void hideSoftInput() {
        InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
    }
}

实现之后的大概样子是这样的
网络编程

这个是在本机上测试的,当然也可以在不同手机上测试,只要确定俩个手机ip网段相同,可以互相访问就可以了

代码已上传GitHub https://github.com/renxh4/RXHApp 欢迎star

相关标签: 网络编程