29(套接字)就是网络编程

通过java程序实现网络之间的数据传输   底层基于网络来传输的流

网路模型

 

IP地址:确定再网络中的位置  ipv4 由4位0-255之间的数组成的--192.168.0.1   ipv6

端口:计算机和外部进行数据交互的媒介---端口号(0-65535  16位二进制数) 0-1023这些端口号大部分被

我们的系统占用了紧密绑定一些服务,

注册端口:1024到49151.它们松散的绑定一些服务

动态和/或私有端口:从49152到65535,这些端口时应用程序使用的动态端口,应用程序一般不会主动使用这些端口

域名:给ip取得好记的名称  通过DNS中央解析器可以映射到对应的IP

一:InetAddress 类

java提供了InetAddress类来代表IP地址,InetAddress下还有2个子类:Inet4Address、Inet6Address

 

UDP: 底层基于流,底层是通过数据包来进行数据的传输,数据包大小一般不能超过64kb。不会建立连接(不检测连接状态,不检测传输东西是否有用),所以对我们来说

传输数据不可靠,但是传输速度快。使用场景 :视频聊天 

创建UDP数据连接采用的类是 DatagramSocket(实现类)   Datagrampacket(数据包类)

发送端:

1.创建套接字对象

2.创建需要发送的数据包(指定要发送的数据长度以及ip地址和端口号)

3.发送数据包

4.关流

public class UDPSenderDemo {

    public static void main(String[] args) throws IOException {
        //UDP传输的发送端
        //创建套接字的对象 -------指定要传输的IP和端口
        DatagramSocket ds=new DatagramSocket();
        //创建一个待传输的数据包
        //因为是通过数据包传输的,所以IP地址我只要给数据包指定就好
        //第一个参数是用传输的数据的字节数组
        //第二个参数真正要发送的数据长度(最大和byte数组长度一致)
        //第三个参数指明要传输的IP地址和端口
        DatagramPacket dp=new DatagramPacket("你好".getBytes(), "你好".getBytes().length,new InetSocketAddress("127.0.0.1", 8009));
        //发送数据包
        ds.send(dp);
        //关流  -----底层字节流
        ds.close();

}
}

 

接收端

1.创建套接字对象(绑定具体的端口号)

2.创建需要接收的数据包(指定真实接收数据的长度)

3.接收数据包

4.关流

5.解析数据包

public class UDPReceiverDemo {

    public static void main(String[] args) throws IOException {
        //创建接收端套接字对象
        //接收端的套接字的话就是要采用含端口的构造方法,因为不管什么IP地址发送给我数据,我都是通过端口来交互数据
        DatagramSocket ds=new DatagramSocket(8009);
        //创建数据包用于接收数据
        //第二个参数代表实际接收数据的长度,可以设置的小一点
        DatagramPacket dp=new DatagramPacket(new byte[1024], 1024);
        //接收数据把数据放置在数据包中
        ds.receive(dp);
        //关流
        ds.close();
        //解析数据包
        //dp.getData() --获取数据---字节数组
        //dp.getLength()--获取数据的长度
        System.out.println(new String(dp.getData(),0,dp.getLength()));
        //获取IP地址和端口
        System.out.println(dp.getAddress());
        System.out.println(dp.getPort());
        //先开启接收端
        //后开启发送端

    }

}

 案例:

1.通过UDP实现检测的聊天室(通过线程实现)

public class UDPsenderDemo2 {
    public static void main(String[] args) {
        //开启线程
        new Thread(new Sender()).start();
        new Thread(new Receiver()).start(); 
    }
}


//发送端
class Sender implements Runnable{
    //声明对象
    DatagramSocket ds;
    Scanner sc;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        //对象初始化
        try {
            ds=new DatagramSocket();    
            sc=new Scanner(System.in);
            while(true) //保证一直发送数据
            {
                //录入数据
                byte[]bs=sc.nextLine().getBytes();
                //创建发送的数据包
                DatagramPacket dp=new DatagramPacket(bs,bs.length,new InetSocketAddress("127.0.0.1",8090));
                //发送数据包
                ds.send(dp);
            }
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

//接收端
class Receiver implements Runnable{
    DatagramSocket ds;
    DatagramPacket dp;
    @Override
    public void run() {
        //对象初始化
        try {
            ds=new DatagramSocket(8090);
            dp=new DatagramPacket(new byte[1024],1024);
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        while(true)
        {
            try {

                //接收数据包
                ds.receive(dp);
                //解析数据包    
                System.out.println(new String(dp.getData(),0,dp.getLength()));
                System.out.println(dp.getAddress());
                System.out.println(dp.getPort());
            }

            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }}




    }

}

TCP:底层基于流:建立连接。可靠,传输速度慢

TCP通过字节流直接传输数据不需要数据包,就没有传输数据的限制

适用场景:传输文件,和下载电影等

客户端(Socket)

1.创建TCP客户端对象

2.发起链接(指明要发送的IP和端口)

3.获取自带的字节输出流

4.根据自带的字节流往服务器端写出数据

5.通知服务器已经写完、关流

 

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

public class TCPClientDemo {
public static void main(String[] args) throws IOException {
    //创建TCP套接字对象
    Socket s=new Socket();
    //发起链接---指定链接的IP和端口
    s.connect(new InetSocketAddress("127.0.0.1",9008)); //connect会有阻塞
    //获取套接字对象自带的字节输出流
    //写出的数据默认往服务器写
    OutputStream os=s.getOutputStream();
    
    //通过自带的字节输出流写数据
    os.write("服务器你好。。。".getBytes());
    
    //通知服务器数据已写完
    s.shutdownOutput();
    
    //获取自带字节输入流
    InputStream in =s.getInputStream();
    //读取数据
    byte[]bs=new byte[1024];
    int len=-1;
    while((len=in.read(bs))!=-1)
    {
        System.out.println(new String(bs,0,len));
    }
    //通知服务器已经读取完成
    s.shutdownInput();
    //关流
    os.close();
}
}

 

服务器端(ServiceSocket)

1.创建TCP服务器端对象。绑定端口

2.接收链接

3.获取自带的字节流

4.通过自带的字节流进行数据读取

5.通知客户端已经读取完成、关流

6关流

 

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

public class TCPServiceDemo {
public static void main(String[] args) throws IOException {
    //创建一个TCP服务器端对象---绑定端口
        ServerSocket ss=new ServerSocket(9008);
        //接收链接,为什么呢因为Socket有自带的InputStream
        System.out.println("接收");
        Socket s=ss.accept(); //阻塞
        System.out.println("接收完成");
        //读取传过来的数据
        //获取自带的输入流
        InputStream in=s.getInputStream();
        //自建缓冲区
        byte[]bs=new byte[1024];
        int len=-1;
        while((len=in.read(bs))!=-1)  
        {
            System.out.println(new String(bs,0,len));
        }
        //通知客户端数据以读完
        s.shutdownInput();
        
        //获取一个自带的字节输出流
        OutputStream os =s.getOutputStream();
        //往客户端写出数据
        os.write("你也好".getBytes());
        //通知客户端已经写完
        s.shutdownOutput();
        in.close();
}
}

用TCP实现客户端上传文件,服务端复制文件

客户端

package cn.tedu.inernet.tcp;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class TCPFileCopyClient {
    public static void main(String[] args) throws IOException {
        //创建TCP客户端对象
        Socket s=new Socket();
        //发起链接
        s.connect(new InetSocketAddress("127.0.0.1", 9009));
        //文件类对象
        File file=new File("D:\\1.mp4");
        //把外部文件读取进来
        FileInputStream fis=new FileInputStream
                (file);
        //获取自带输出流
        OutputStream os=s.getOutputStream();
        //获取文件名称
        //先传文件名长度
        os.write(file.getName().getBytes().length-128);//文件名长度值
        //传文件名内容
        os.write(file.getName().getBytes());
        byte[] bs=new byte[1024*1024*10];
        int len=-1;
        while((len=fis.read(bs))!=-1){
            //往服务器端写数据
            os.write(bs,0,len);
        }
        
        //通知服务器端已写完
        s.shutdownOutput();
        //关流
        os.close();
        fis.close();
    }
}

服务端

package cn.tedu.inernet.tcp;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPFileCopyServer {
    public static void main(String[] args) throws IOException {
        //获取TCP服务器端的对象---绑定端口
        ServerSocket ss=new ServerSocket(9009);
        //接收链接
        Socket s=ss.accept();
        //获取自带字节输入流---读取客户端发来的数据
        InputStream in=s.getInputStream();
        //接收文件名长度值
        byte length=(byte)in.read();
        //新建字节数组
        byte[] bts=new byte[length+128];
        //按照这个字节数组读取文件名内容
        in.read(bts);//字节数组里存满了文件名内容
        //创建文件字节输出流对象
        FileOutputStream fos=new FileOutputStream(new File("D:\\javase\\"+new String(bts)));
        byte[] bs=new byte[1024*1024*10];
        int len=-1;
        while((len=in.read(bs))!=-1){
            //往外部文件写数据
            fos.write(bs, 0, len);
        }
        
        //通知客户端已经读取完毕
        s.shutdownInput();
        //关流
        in.close();
        fos.close();
    }

}

 

posted @ 2019-07-27 14:51  三十六烦恼风x  阅读(240)  评论(0)    收藏  举报