Java基础(十八)Socket网络编程

网络编程(套接字)

先解释一下套接字:Socket
所谓套接字,实际上是一个通信端点,每个套接字都有一个套接字序号,包括主机的IP地址与一个16位的主机端口号,即形如(主机IP地址:端口号)。例如,如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)。总之,套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的IP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。通信时,其中的一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过网络接口卡的传输介质将这段信息发送给另一台主机的Socket中,使这段信息能传送到其他程序中。因此,两个应用程序之间的数据传输要通过套接字来完成…

1.概念:

基于网络进行数据传输(IO流)
物理层,数据链路层,网络层,传输层(UDP,TCP),会话层,表示层,应用层
IP地址:主机在网络中的位置
IPv4是由0~255的数字组成16.30
域名解析器:把域名解析成对应的IP
端口:让计算机和外界进行数据交互的媒介 端口号(0-65535)从0~1024端口号基本都被系统占用了,使用时从后面开始使用

2.InetSocketAddress类—可以代表IP地址和端口号

package cn.tedu.net.address;

import java.net.InetSocketAddress;

public class InetSocketAddressDemo {
    public static void main(String[] args) {
        //创建代表IP地址和端口号的对象
        //localhost解析成127.0.0.1永远指向本地
        InetSocketAddress is=new InetSocketAddress("localhost",8080);

        //获取信息
        //获取IP地址
        System.out.println(is.getAddress());
        //获取主机名
        System.out.println(is.getHostName());
    }
}

3.UDP协议

底层基于流,传输不建立连接,不安全(不可靠)但是速度快
底层根据数据包(64KB)来进行传输
适用场景:直播、视频、音频等等

DatagramSocket、DatagranPacket
发送端
1.创建UDP发送端对象
2.创建数据包(指定IP地址和端口以及要发送的数据)
3.发送数据包
4.关流

package cn.tedu.net.upd;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UDPSenderDemo {
    public static void main(String[] args) throws IOException {
        //创建UDP发送端的对象

        DatagramSocket ds=new DatagramSocket();
        //创建数据包对象---准备发送数据
        //第一个参数代表发送的数据
        //第二个参数代表实际发送数据内容长度
        //第三个参数代表IP地址和端口号
        DatagramPacket dp=new DatagramPacket("早上好".getBytes(),"早上好".getBytes().length,
                new InetSocketAddress("127.0.0.1",8081));

        //发送数据包
        ds.send(dp);

        //关流
        ds.close();
    }
}

接收端
1.创建UDP接收端对象,监听端口号
2.创建数据包(接收发送端发送数据)
3.接收数据包
4.关流
5.解析数据包

package cn.tedu.net.upd;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPReceiverDemo {
    public static void main(String[] args) throws SocketException {
        //创建UDP接收端的对象---监听发送端的端口号
        DatagramSocket ds=new DatagramSocket(8081);

        //创建数据包对象--接收数据
        //第一个参数代表来接收数据的字节数组
        //第二个参数代表真实的接收数据内容长度
        DatagramPacket dp=new DatagramPacket(new byte[1024],1024);

        //接收发送端发送的数据
        ds.receive(dp);//会让线程产生阻塞状态
        //关流
        ds.close();

        //解析数据包
        //返回IP地址
        System.out.println(dp.getAddress());
        //getData()---接收到的数据
        //getLength()---接收数据内容长度
        //展示接收的数据
        System.out.println(new String(dp.getData(),0,dp.getLength()));
    }
}

练习:
通过UDP即实现简易聊天室(线程实现)

package cn.tedu.net.upd;

import com.sun.xml.internal.ws.resources.SenderMessages;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.Scanner;

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

//定义类---代表发送端
class Sender implements Runnable{
    //发送过程
    @Override
    public void run() {

        try {
            //创建UDP发送端对象
            DatagramSocket ds=new DatagramSocket();
            //创建Scanner类对象
            Scanner 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",9090));
                //发送数据包
                ds.send(dp);
            }

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


//定义类---代表线程执行任务信息(接收端)
class Receiver implements Runnable{
    //指定接收过程
    @Override
    public void run() {
        try{
            //创建UDP接收端对象---监听端口号
            DatagramSocket ds=new DatagramSocket(9090);
            //创建接收数据的数据包对象
            DatagramPacket dp=new DatagramPacket(new byte[1024],1024);
            //保证可以一直接收数据
            while (true){
                //接收数据
                ds.receive(dp);
                //解析数据包
                System.out.println(dp.getAddress());
                System.out.println(new String(dp.getData(),0,dp.getLength()));
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }


}

聊天窗口出来啦!

在这里插入图片描述

4.TCP协议

底层基于流,传输建立连接(三次握手),安全(可靠)传输速度慢
适用场景:上传和下载、聊天等等
Socket/ServerSocket
客户端
1.创建TCP客户端对象
2.发起连接(指定IP地址和端口号)
3.获取自带字节输出流往服务器端写出数据
4.写出数据
5.通知服务端数据已经发送完毕
6.关流

package cn.tedu.net.upd;

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();

        //发起连接
        s.connect(new InetSocketAddress("127.0.0.1",9092));//让线程对象阻塞

        //获取自带的字节输出流
        //默认往服务器端传输
        OutputStream os=s.getOutputStream();

        //写出数据
        os.write("下午好".getBytes());

        //通知服务器端数据已经发送完毕
        s.shutdownOutput();

        //从服务器端来读取数据
        //获取自带字节输入流
        InputStream is=s.getInputStream();
        //自建缓冲区---自荐书组
        byte[] bs=new byte[1024];
        int len=-1;
        while ((len=is.read(bs))!=-1){
            //展示读取到的内容
            System.out.println(new String(bs,0,len));
        }

        //通知服务器端数据已经读取完毕
        s.shutdownInput();
        //关流
        s.close();
    }
}

服务器端
1.创建TCP服务器端对象,监听端口号
2.接收连接
3.获取自带字节输入流从客户端来读取数据
4.读取数据
5.通知客户端数据已经读取完毕
6.关流

package cn.tedu.net.upd;

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

public class TCPServerSocketDemo {
    public static void main(String[] args) throws IOException {
        //创建TCP服务端对象--监听端口号
        ServerSocket ss=new ServerSocket(9092);

        //接收连接
        Socket s=ss.accept();//让线程对象进行阻塞

        //获取自带的字节输入流(默认读取客户端发送数据)
        InputStream is=s.getInputStream();

        //自建缓冲区---自荐书组
        byte[] bs=new byte[1024];
        int len=-1;
        //让线程对象阻塞
        while ((len=is.read(bs))!=-1){
            //把读取到的内容进行展示
            System.out.println(new String(bs,0,len));
        }
        //通知客户端数据已经接收完毕
        s.shutdownInput();

        //把服务器端数据发送到客户端
        //获取字节输出流---往客户端发送数据
        OutputStream os=s.getOutputStream();

        //发送数据
        os.write("你也好".getBytes());

        //通知客户端数据已经发送完毕
        s.shutdownOutput();

        //关流
        s.close();
        ss.close();
    }
}

在这里插入图片描述在这里插入图片描述

让线程阻塞的方法—receive()、connect()、accept()、write()、read()

练习
通过TCP实现文件的上传和下载、
客户端:

package cn.tedu.net.upd;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;

public class TCPCopyFileClientDemo {
    public static void main(String[] args) throws IOException {
        //创建TCP客户端的对象
        Socket s=new Socket();

        //发起连接
        s.connect(new InetSocketAddress("127.0.0.1",9010));

        //创建代表文件类的对象
        File file=new File("E:\\Linux\\CentOS-7-1908");
        //创建文件字节输入流对象(来读取外部文件)
        FileInputStream fis=new FileInputStream(file);

        //获取自带字节输出流对象
        OutputStream os=s.getOutputStream();

        //把文件名字的长度值发送到服务器端
        //文件名的字节数(字节值)
        os.write(file.getName().getBytes().length);
        //发送文件名内容
        os.write(file.getName().getBytes());

        //读取外部文件内容
        //自建缓冲区--自建数组
        byte[] bs=new byte[1024*1024*50];//50MB
        int len=-1;
        while ((len=fis.read(bs))!=-1){
            //边读边写
            os.write(bs,0,len);
        }
        //通知服务器端数据已经发送完毕
        s.shutdownOutput();
        //关流
        fis.close();
        s.close();

    }
}

服务器端:

package cn.tedu.net.upd;

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

public class TCPCopyFileServerDemo {
    public static void main(String[] args) throws IOException {
        //创建TCP服务器端对象---监听端口号
        ServerSocket ss=new ServerSocket(9010);

        //接收连接
        Socket s=ss.accept();

        //获取自带字节输入流对象
        InputStream is=s.getInputStream();

        //读取发送文件名内容的长度值---字节值
        byte length=(byte) is.read();
        //定义一个字节数组来接收文件内容
        byte[] bb=new byte[length];
        //把客户端发送过来的文件名的内容读取到字节数组里
        is.read(bb);

        //创建文件字节输出流对象
        //从客户端获取文件名称?
        FileOutputStream fos=new FileOutputStream("F:\\"+new String(bb));

        //读取客户端发送的数据
        //自建缓冲区---自荐书组
        byte[] bs=new byte[1024*1024*50];
        int len=-1;
        while ((len=is.read(bs))!=-1){
            //边读边写
            fos.write(bs,0,len);
        }

        //通知客户端数据已经接收完毕
        s.shutdownInput();

        //关流
        fos.close();
        s.close();
        ss.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张艳霞zhangyx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值