18.网络编程

网络编程

又称为Socket编程。

Java中网络编程主要是以Java语言完成信息数据在网络上的传输。

网络

计算机网络,指的是将不同地理位置的多台计算机连接起来,可以实现信息共享和信息传输。

Java是Internet上的语言,提供了对网络应用程序的支持,所以,我们使用Java开发一些常见的网络应用。

网络通信怎么完成?

1.通过网络地址(IP地址)+端口 确定计算机以及具体的应用。

2.确定了计算机之后,完成传输(TCP/UDP)

Java实现网络编程的要素

1.IP地址类:InetAddress

2.端口:int 值;

3.TCP/UDP操作相关类:Socket

IP地址 InetAddress:

32位二进制数值以点分的形式表示,分成4份

0.0.0.0 ~ 255.255.255.255

本地回环地址:127.0.0.1

本地主机名:localhost

package com.day18.socket;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        //获取InetAddress对象的方法,传主机名,返回主机名和IP地址
        InetAddress address = InetAddress.getByName("localhost");
        System.out.println(address);
        //传IP地址,返回的只有IP地址
        InetAddress address1 = InetAddress.getByName("127.0.0.1");
        System.out.println(address1);

        System.out.println(address.getHostName());//主机名
        System.out.println(address.getHostAddress());//主机地址

        //获取本地主机实际的IP地址+主机名的InetAddress对象
        InetAddress address2 = InetAddress.getLocalHost();
        System.out.println(address2);

        //传入网站的信息,获取对象
        InetAddress address3 = InetAddress.getByName("www.baidu.com");
        System.out.println(address3);
    }
}

端口号

端口号是确定应用的唯一标识,端口号是一个16位的整数,

范围是0-65535,TCP和UDP各有65535个端口,单个协议下的端口号不能冲突。

公认端口:0-1023 被预先定义的服务占用端口

http:80

https:443

注册端口:

tomcat:8080

mysql:3366

oracle:1521

查看端口是否被占用:netstat-ano

InetSocketAddress 该类实现IP套接字地址(IP地址+端口号)

InetSocketAddress(InetAddress addr, int port)

从IP地址和端口号创建套接字地址。

Socket 该类实现客户端套接字(也称为“套接字”)。

Socket(InetAddress address, int port)

创建流套接字并将其连接到指定IP地址的指定端口号。

ServerSocket 这个类实现了服务器套接字

ServerSocket(int port)

创建绑定到指定端口的服务器套接字。

网络传输的协议

满足IP地址+端口的使用后,需要选定一个传输方式,来实现数据的传输

传输协议都定义在传输层,分为TCP协议和UDP协议

TCP协议:

使用之前,先要建立TCP连接,形成传输通道,采用3次握手,点对点的通信,是一种安全的传输协议。

TCP通信中,必须要有的应用进程:客户端、服务端

TCP协议可以传送大量的数据,传输完毕,需要释放连接,效率比较低。

UDP协议:

将数据、源地址、目标地址封装在数据包中,直接将数据包发送就行,

发送的时候,不需要建立连接,也不会去管对方是否能收到数据,接收方如果接受到了,也不会做出回应

是一种不安全的传输协议。

每个数据大小限制在64kb以内,发送完不需要是否,开销小、速度快。

分别使用TCP和UDP实现信息传输

TCP实现消息发送

客户端发送消息到服务端,服务端接收到数据把数据显示在控制台

package com.day18.tcp1;

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

public class TCPClient {
    public static void main(String[] args) {

        try {
            //实现步骤
            //1.连接服务器的Socket
            //创建Socket
            InetAddress address = InetAddress.getByName("127.0.0.1");
            int port=8999;
            Socket socket = new Socket(address, port);
            //2.发送消息
            //通过socket,获取输出流对象,向服务器写内容
            OutputStream os = socket.getOutputStream();
            os.write("你好,我现在在使用TCP编程发送消息".getBytes());
            //3.关闭资源
            os.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
package com.day18.tcp1;

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

public class TCPServer {
    public static void main(String[] args) {

        try {
            //1.建立服务端ServerSocket
            ServerSocket serverSocket = new ServerSocket(8999);
            //等待用户连接
            while (true){
                //调用accept()方法,侦听到连接此服务器的Socket并返回
                Socket accept = serverSocket.accept();
                //通过返回的socket对象获取输入流
                InputStream is = accept.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                int len;
                byte[] bytes = new byte[1024];
                //3.接受用户消息,读取消息
                while ((len = is.read(bytes)) != -1){
                    baos.write(bytes,0,len);
                }
                System.out.println(baos.toString());

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
UDP 实现消息发送

使用的类:

DatagramPacket 该类表示数据报包。

DatagramPacket(byte[] buf, int length, InetAddress address, int port)

构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。

DatagramSocket 此类表示用于发送和接收数据报数据包的套接字。

DatagramSocket(int port)

构造数据报套接字并将其绑定到本地主机上的指定端口。

package com.day18.udp1;

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

//发送方
public class UDPClient {
    public static void main(String[] args) throws IOException {
        //创建数据报包对象
        //定义数据
        String data = "你好,我在使用UDP编程发送数据";
        byte[] bytes = data.getBytes();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        int port=9999;
        DatagramPacket packet =
        new DatagramPacket(bytes, 0, bytes.length, address, port);
        //创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket();

        //发送数据
        socket.send(packet);
        System.out.println("数据发送完毕");
        socket.close();

    }
}
package com.day18.udp1;

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

//接收方
public class UDPServer {
    public static void main(String[] args) throws IOException {
        //创建DatagramSocket对象,接收对象
        DatagramSocket socket = new DatagramSocket(9999);

        //创建一个数据包对象,用来接收数据
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
        //接收数据放入到数据包中
        socket.receive(packet);
        //从数据包中拿去数据,拿出来是字节数组
        byte[] data = packet.getData();
        //字节数组转字符串
        String s = new String(data, 0, data.length);
        System.out.println(s.trim());

    }
}
UDP+多线程实现聊天
package com.day18.udp2;

import java.io.BufferedReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

//发送方
public class TalkSend implements Runnable{
    //创建需要的对象
    private DatagramSocket socket;
    private String toIP;//目标IP地址
    private int toPort;//目标端口
    private int fromPort;//来自端口
    //    private BufferedReader reader;

    Scanner scanner = new Scanner(System.in);

    public TalkSend(String toIP, int toPort, int fromPort) {
        this.toIP = toIP;
        this.toPort = toPort;
        this.fromPort = fromPort;

        try {
            //创建对象的同时,把socket赋值
            socket = new DatagramSocket(fromPort);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            while (true){
                //读取输入信息
                String s = scanner.next();
                byte[] bytes = s.getBytes();
                InetAddress address = InetAddress.getByName(toIP);

                //将写入的数据,封装到数据包中
                DatagramPacket packet =
                new DatagramPacket(bytes, 0, bytes.length, address, toPort);
                //发送
                socket.send(packet);
                //如果不准备聊天了,发送bye作为结束
                if ("bye".equals(s)){
                    break;
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        socket.close();
    }
}
package com.day18.udp2;

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

public class TalkReceive implements Runnable{
    private DatagramSocket socket;
    private String messageFrom;
    private int port;

    public TalkReceive(String messageFrom, int port) {
        this.messageFrom = messageFrom;
        this.port = port;
        //开发端口号,创建DatagramSocket对象
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            while (true){
                //接收消息
                byte[] bytes = new byte[1024];
                DatagramPacket packet =
                new DatagramPacket(bytes, 0, bytes.length);

                //接收数据,存入packet
                socket.receive(packet);

                //把数据输出
                byte[] data = packet.getData();
                String s = new String(data,0,data.length);
                System.out.println(messageFrom+":"+s.trim());

                //退出判断,如果发过来的数据是bye,则结束循环
                if ("bye".equals(s)){
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        socket.close();

    }
}
package com.day18.udp2;
//小红发给小明
public class TalkTest1 {
    public static void main(String[] args) {
        new Thread(new TalkSend("localhost", 9999, 7777)).start();
        new Thread(new TalkReceive("小明", 8888)).start();

    }
}
package com.day18.udp2;
//小明发给小红
public class TalkTest2 {
    public static void main(String[] args) {
        new Thread(new TalkSend("localhost", 8888, 6666)).start();
        new Thread(new TalkReceive("小红", 9999)).start();

    }
}
使用 TCP 完成图片上传
package com.day18.tcp2;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

//图片上传的客户端
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建Socket对象
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);

        //获取输出流
        OutputStream os = socket.getOutputStream();

        //把文件读进内存,输出流将文件写出
        FileInputStream fis = new FileInputStream("D://hello//java//No1.jpg");
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes) )!= -1){
            os.write(bytes,0,len);
        }
        //需要调用方法将之前的上传操作结束
        socket.shutdownOutput();
        //拿到服务端返回的消息,通过socket对象,获取输入流
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        int len1;
        byte[] bytes1 = new byte[1024];
        //接受用户消息,读取消息
        while ((len1 = is.read(bytes1)) != -1){
            baos.write(bytes1,0,len1);
        }
        System.out.println(baos.toString());

        fis.close();
        os.close();
        socket.close();
    }
}
package com.day18.tcp2;

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

//接受图片的服务端
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(9090);

        //等待客户端连接,获取客户端的socket
        Socket accept = serverSocket.accept();
        //获取socket中的输入流
        InputStream is = accept.getInputStream();

        //拿到输入流中的内容,再把内容写入服务器中
        FileOutputStream fos = new FileOutputStream("receive.jpg");

        byte[] bytes = new byte[1024];
        int len;
        //读内容,读的同时往socket中的输出流写内容
        while ((len = is.read(bytes) )!= -1){
            fos.write(bytes,0,len);
        }

        //把图片上传成功的信息返回给客户端
        OutputStream os = accept.getOutputStream();
        os.write("图片上传成功".getBytes());

        is.close();
        fos.close();
        os.close();
        accept.close();
        serverSocket.close();
    }
}
  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值