网络编程

1、IP地址和端口号

  通过IP地址可以连接到指定计算机,但如果想访问目标计算机中的某个应用程序,还需要指定端口号。在计算机中,不同的应用程序是通过端口号区分的。端口号是用两个字节(16位的二进制数)表示的,它的取值范围是0~65535(2的16次方为65536),其中,0~1023之间的端口号是用于一些知名的网络服务和应用,用户的普通应用程序需要使用1024以上的端口号,从而避免端口号被另外一个应用或服务所占用。

2、使用UDP协议实现通信功能

  UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。

  由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失有一两个数据包,也不会对接收结果产生太大影响。

  但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。

  DatagramPacket数据包的作用就如同“集装箱”,可以将发送端或者接收端的数据封装起来。然而运输货物只有“集装箱”是不够的,还需要有码头。DatagramPacket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包。

 

 发送端于接收端交互图解

发送端

package com.zy.demo2;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class UDPSend {

    public static void main(String[] args) throws Exception {
        
        //1创建码头
        DatagramSocket datagramSocket = new DatagramSocket();
        //2创建集装箱
        String data="中国食用油";
        byte[] bytes = data.getBytes();
                
        //3发送数据
        //根据名字获取主机(机器互联)
        InetAddress byName = InetAddress.getByName("192.168.219.61");//getByName("127.0.0.1")也可以写ip,不一定非得是主机名     
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, byName, 9999);              
        datagramSocket.send(datagramPacket);
   //4释放资源
        datagramSocket.close();

    }

}

接收端

package com.zy.demo2;

import java.io.File;
import java.io.FileOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceive {

    public static void main(String[] args) throws Exception {
        //1创建码头
        DatagramSocket datagramSocket = new DatagramSocket(9999);//双方约定的     
        
        //2创建集装箱
        byte b[]=new byte[1024];//空的字节数组
        DatagramPacket datagramPacket = new DatagramPacket(b, b.length);
               
       //3收货
        datagramSocket.receive(datagramPacket);//线程阻塞!!!(没收到时)        
       
        //4查看货物
        System.out.println(new String(b));
        
        //5释放资源
        datagramSocket.close();
    }

}

先运行接收端,虚拟灯一直亮着等待发送端发送数据

再运行发送端,然后回到接收端console

2、使用TCP实现服务与客户端通信

  TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。

  区别在于,UDP中只有发送端和接收端,不区分客户端和服务端,计算机之间可以任意地发送数据。而TCP通信是严格区分客户端和服务端的,在通信时。必须先由客户端去连接服务端才能实现通信,服务端不可以主动连接客户端,并且服务端程序需要事先启动,等待客户端的连接。

  通信时。首先创建代表服务端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务端发送连接请求,服务端响应请求,两者建立连接开始通信。

服务端程序

package LESSON13;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPserver {

    /**
     使用TCP接收数据
     创建接收端Socket对象
     监听(阻塞)
     获取输入流对象
     获取数据
     输出数据
     释放资源
     
     
     ServerSocket此类实现服务器套接字。
     ServerSocket(int port) 
          创建绑定到特定端口的服务器套接字
     * @throws Exception 
     
     
     */
    public static void main(String[] args) throws Exception {    
        ServerSocket server = new ServerSocket(9999);// 创建接收端Socket对象        
        Socket s = server.accept();//监听(阻塞)等待连接
        
        //通信
        InputStream in=s.getInputStream();// 获取输入流对象(接收数据)        
        byte b[]=new byte[1024];
        in.read(b);//接收客户端发来的信息    
    
        
        OutputStream out=s.getOutputStream();//获取输出流对象(发送数据)
        out.write("你好,我是服务器".getBytes());//向客户端发送信息
        
            
        // InetAddress getInetAddress() 返回套接字连接的地址。 
        InetAddress address = s.getInetAddress();        
        System.out.println("client"+"\t"+address.getHostAddress());
        System.out.println(new String(b).trim());
        
        in.close();
        s.close();
        //ss.close();
        
        
        
        
        

    }

}

客户端程序

package LESSON13;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class TCPclient {

    /**
    使用TCP发送数据
    创建发送端Socket对象(创建连接)
    获取输出流对象
    发送数据
    释放资源
    Socket(InetAddress address, int port) 
          创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
          
     Exception in thread "main" java.net.ConnectException: Connection refused: connect
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        InetAddress address=InetAddress.getByName("localhost");//获取本地IP地址
        Socket client=new Socket(address, 9999);//创建发送端Socket对象(创建连接)
        //通信
        OutputStream out=client.getOutputStream();//获取输出流对象(发送数据)
        out.write("服务器你好,我是客户端".getBytes());//发送数据
        
        
        InputStream in=client.getInputStream();//获取输入流睡醒(接收数据)
        byte b[]=new byte[1024];
        in.read(b);//接收服务器发送来的信息
        System.out.println(new String(b).trim());
        
        out.close();
        client.close();
        
        
        
        
        

    }

}

先运行服务端,再运行客户端

 

posted @ 2019-06-27 23:27  勤奋的园  阅读(185)  评论(0编辑  收藏  举报