Java网络编程(TCP/UDP)

首先我们先了解一下计算机网络的基本知识。

什么是网络?

将不同区域的计算机连接到一起。按照区域的大小可分为局域网,城域网,广域网(互联网)。

地址即IP地址,确定在网络上的一个绝对地址。

端口号:区分计算机上的软件, 占用两个字节 ,端口号范围为: 0-65535, 一共65536个端口号。

1. 在同一个协议下端口号不能重复,不同的协议可以重复

2. 1024以下的端口号尽量不要使用。有可能已被占用,如80–http 21–ftp

**资源定位:**URL 统一资源定位符 URI:统一资源

数据的传输

1、协议:TCP与UDP协议

1.TCP协议:面向连接 ,安全可靠,效率低下,类似于打电话,有三次握手

2.UDP协议:非面向连接,不可靠,效率高,类似于短信

2、传输(包括:封装与拆分),先封装,后拆分。

然后,进行编程需要了解java.net包下 面的如下几个类

1、InetAddress、InetSocketAddress

2、URL

3、TCP:ServerSocket、 Socket

4、UDP:DatagramSocket、DatagramPacket

1、IP地址及端口号

package ip;

/**
 * 没有封装端口
 */

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

public class Demo01 {
    public static void main(String[] args) throws UnknownHostException {
        //使用getLocationHost方法创建InetAddree对象
        InetAddress addr = Inet4Address.getLocalHost();
        System.out.println(addr.getHostAddress());//返回ip地址
        System.out.println(addr.getHostName());//输出计算机名

        //根据域名得到InetAddress对象
        addr = InetAddress.getByName("www.163.com");
        System.out.println(addr.getHostAddress());//返回服务器的ip
        System.out.println(addr.getHostName());
        //根据ip得到InetAddress对象
        addr = InetAddress.getByName("202.201.14.181");
        System.out.println(addr.getHostAddress());//返回服务器的ip
        System.out.println(addr.getHostName());//地址不存在或者为了安全性DNS域名不能解析 就返回ip 182.140.147.57
    }
}

运行结果:

10.12.4.73

WIN-0HGJ9QM2MEG

61.188.191.84

www.163.com

202.201.14.181

202.201.14.181


package ip;

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

/**
 * 封装端口:在InetAddress基础上+端口
 */

public class Demo02 {
    public static void main(String[] args) throws UnknownHostException {
        InetSocketAddress address = new InetSocketAddress("localhost",9999);
        //address = new InetSocketAddress(InetAddress.getByName("127.0.0.1"),9999);
        System.out.println(address.getHostName());
        System.out.println(address.getPort());
        InetAddress addr = address.getAddress();//获得地址
        System.out.println(addr.getHostAddress());//返回:IP地址
        System.out.println(addr.getHostName());//输出计算机名

    }
}

运行结果:

localhost

9999

127.0.0.1

localhost

2、URL,统一资源定位符,它是一个具体的URI。

URL由四部分组成:协议,存放资源的主机域名,端口号,资源文件名

URL(String protocol, String host, int port, String file)

package URL;

import java.net.MalformedURLException;
import java.net.URL;

public class Demo01 {
    public static void main(String[] args) throws MalformedURLException {
        //绝对路径构建
        URL url = new URL("http://www.baidu.com:80/index.html#bb?uname=liguodong");
        //url = new URL("http://www.baidu.com:80/index.html?uname=liguodong");
        System.out.println("协议:"+url.getProtocol());
        System.out.println("域名:"+url.getHost());
        System.out.println("端口:"+url.getPort());
        System.out.println("资源:"+url.getFile());
        System.out.println("相对路径的资源:"+url.getPath());//用得比较多
        System.out.println("緢点:"+url.getRef());//緢点    bb?uname=liguodong
        System.out.println("参数:"+url.getQuery());//参数:存在緢点返回null,不存在,返回正确

        url = new URL("http://www.baidu.com:80/a/");
        url = new URL(url,"b.txt");
        System.out.println(url.toString());

    }
}

运行结果:

协议:http

域名:www.baidu.com

端口:80

资源:/index.html

相对路径的资源:/index.html

緢点:bb?uname=liguodong

参数:null

http://www.baidu.com:80/a/b.txt


package URL;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;

/**
 * 获取资源:源代码
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        URL url = new URL("http://www.baidu.com");//有时,如果没有资源,主页即是默认资源。
        //获取资源
        //这种方式会出现乱码出现乱码的情况分别是字节数不够或者编码不统一,这种情况明显是编码不统一。
        //因此可以使用直接将平台的编码改掉,或者使用转换流
        /*InputStream is = url.openStream();
        byte[] flush = new byte[1024];
        int len=0;
        while(-1!=(len=is.read(flush)))
        {
            System.out.println(new String(flush,0,len));
        }
        is.close();*/   

        BufferedReader br = new BufferedReader(
                new InputStreamReader(url.openStream(),"utf-8"));
        BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream("baidu.html"),"utf-8"));

        String msg = null;
        while((msg=br.readLine())!=null)
        {
            System.out.println(msg);
            System.out.println();
            bw.append(msg);
            bw.newLine();
        }
        bw.flush();
        bw.close();
        br.close();
    }
}

3、UDP通信:以数据为中心,非面向连接,不安全,数据可能丢失 效率高

DatagramPacket:此类表示数据报包。

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

整体设计

1.客户端

1.1创建客户端

1.2创建数据(字节数组)

1.3打包(DatagramPacket+服务器地址及端口号)

1.4发送

1.5释放数据

2.服务器端

2.1创建服务器(DatagramSocket类+制定端口号)

2.2准备接收容器(字节数组)

2.3包(接收数据)

2.4分析

2.5释放资源

package UDP;

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

/**
 * 服务端
 * 1、创建服务端+端口
 * 2、准备接收容器
 * 3、封装成包
 * 4、接收数据
 * 5、分析数据
 * 6、释放资源
 *
 * DatagramPacket(byte[] buf, int length)
 *     构造 DatagramPacket,用来接收长度为 length 的数据包。
 *
 * DatagramPacket(byte[] buf, int length, InetAddress address, int port)
 *     构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
 *
 */
public class MyServer {
    public static void main(String[] args) throws IOException {
        //1、创建服务端+端口
        DatagramSocket server = new DatagramSocket(8888);

        //2、准备接收容器
        byte[] container = new byte[1024];

        //3、封装成包     DatagramPacket(byte[] buf, int length)构造接收数据包
        DatagramPacket  packet = new DatagramPacket(container, container.length);

        //4、接收数据
        server.receive(packet);

        //5、分析数据
        byte[] data = packet.getData();
        int len = packet.getLength();
        System.out.println(new String(data,0,len));

        //6、释放资源
        server.close();
    }
}
package UDP;

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

/**
 * 客户端
 *1、创建客户端+端口
 *2、准备数据
 *3、打包(发送地点及端口)
 *4、发送
 *5、释放
 *
 */
public class MyClient {
    public static void main(String[] args) throws IOException {
        //1、创建客户端+端口
        DatagramSocket client = new DatagramSocket(6666);

        //2、准备数据
        String msg = "模拟UDP过程";
        byte[] data = msg.getBytes();

        //3、打包(指定发送的地点及端口)
        //DatagramPacket(byte[] buf, int length, SocketAddress address) 构造发送数据报包
        DatagramPacket packet = new DatagramPacket(data, data.length,
                new InetSocketAddress("localhost",8888));

        //4、发送
        client.send(packet);

        //5、释放
        client.close();
    }
}

非面向连接的协议,当服务器打开,服务器能收到数据,当服务器关闭,客户端运行也不会报错,数据也相应的被丢失了。



如果我们发送的数据不是字节数组,而是一个浮点数,因此我们需要进行数据类型转换。本例值得回味。

package UDP;

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

/**
 * 89.12  数据的发送要字节数组,因此将double类型转成字节数组
 * 客户端
 *1、创建客户端+端口
 *2、准备数据   double类型转成字节数组   字节数组输出流   类型转换问题
 *3、打包(发送地点及端口)
 *4、发送
 *5、释放
 */
public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建服务器+端口
        DatagramSocket client = new DatagramSocket(6666);
        //2、准备数据
        double num = 89.12;

        byte[] data = convert(num);

        //3、打包(发送的地点及端口)
        DatagramPacket packet = new DatagramPacket(data, data.length,
                new InetSocketAddress("localhost",8888));
        //4、发送
        client.send(packet);
        //5、释放
        client.close();
    }

    /**
     * 字节数组输出流ByteArrayOutputStream+DataOutputStream数据输出流
     * @param num
     * @return
     * @throws IOException
     */
    public static byte[] convert(double num) throws IOException
    {
        byte[] data = null;
        //有新增方法,不能使用多态
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);

        dos.writeDouble(num);
        dos.flush();

        //获取数据
        data = bos.toByteArray();
        dos.close();
        bos.close();//此方法关闭 ByteArrayOutputStream无效。

        return data;
    }
}
package UDP;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
 * 89.12  数据+类型       用 IO流
 * 服务端
 * 1、创建服务端+端口
 * 2、准备接受容器
 * 3、封装成包
 * 4、接受数据
 * 5、分析数据   字节数组-->double
 * 6、释放资源
 */
public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建服务端+端口
        DatagramSocket server = new DatagramSocket(8888);
        //2、准备接受容器
        byte[] container = new byte[1024];
        //3、封装成包 DatagramPacket(byte[] buf, int length);
        DatagramPacket  packet = new DatagramPacket(container, container.length);
        //4、接受数据
        server.receive(packet);
        //5、分析数据
        double data = convert(packet.getData());
        System.out.println(data);

        //6、释放资源
        server.close();

    }

    /**
     * 字节数组输入类ByteArrayInputStream+DataInputStream数据输入流
     * @param data
     * @return
     * @throws IOException
     */
    public static double convert(byte[] data) throws IOException
    {
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
        double num = dis.readDouble();
        dis.close();
        return num;
    }
}

4、TCP通信: 面向连接,安全可靠,效率低下

ServerSocket:此类实现服务器套接字。

Socket:此类实现客户端套接字。

package TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 必须先启动再连接
 * 1、创建服务器 指定端口 ServerSocket(int port)
 * 2、接收客户端的连接  阻塞式
 * 3、发送数据+接收数据
 */
public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建服务器 指定端口
        ServerSocket server = new ServerSocket(8888);//不同协议端口可以重复,同一协议端口不能重复
        //2、接收客户端的连接
        Socket socket = server.accept();//这里会等待连接
        System.out.println("一个客户端建立连接");

        //2、发送数据
        String msg = "欢迎使用";
        //3、输出流
        /*BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(socket.getOutputStream()));
        bw.write(msg);
        bw.newLine();//一定要加行结束符,不然读不到数据
        bw.flush();*/

        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        dos.writeUTF(msg);
        dos.flush();
    }
}
package TCP;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * 1、创建客户端 必须指定服务器+端口  此时就在连接
 * Socket(String host,int port)
 * 2、接收数据+发送数据
 */
public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        //1、创建客户端 必须指定服务器+端口  此时就在连接
        Socket client = new Socket("localhost",8888);//指定服务器的地址与端口,客户端的端口由服务器自动分配

        //2、接收数据
        /*BufferedReader br = new BufferedReader(
                    new InputStreamReader(client.getInputStream()));
        String echo = br.readLine();//逐行执行,阻塞式方法
        System.out.println(echo);*/

        DataInputStream dis = new DataInputStream(client.getInputStream());
        String echo = dis.readUTF();
        System.out.println(echo);
    }
}

使用TCP时,必须要打开服务器,不然运行客服端会出异常。并且客户端必须要指定服务器的地址与端口,客户端的端口由服务器自动分配。

时间: 2024-10-26 09:21:26

Java网络编程(TCP/UDP)的相关文章

JAVA网络编程-----tcp

java采用TCP传输时利用Socket和ServerSocket Socket和ServerSocket 建立客户端和服务端 建立连接后,通过Socket中的IO流进行数据的传输. 关闭Socket 同样,客户端与服务端是两个独立的应用程序. 演示tcp传输 1.   tcp分客户端和服务端 2.   客户端对应的对象是Socket,服务端对应的对象是ServerSocket. 客户端: 通过查阅socket对象,发现在该对象建立时,就可以连接指定主机, 因为tcp是面向连接的,所以在建立so

Java网络编程(UDP程序设计)

//客户端 package org.udp; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UDPClient { public static void main(String[] args) throws Exception{ DatagramSocket ds = null; byte[] buf = new byte[2014]; DatagramPacket dp = null;

Java网络编程 - 基于UDP协议 实现简单的聊天室程序

最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. 先看一下效果: 实现的效果可以说是非常非常简单,但还是可以简单的看到一个实现原理. "聊天室001"的用户,小红和小绿相互聊了两句,"聊天室002"的小黑无人理会,在一旁寂寞着. 看一下代码实现: 1.首先是消息服务器的实现,功能很简单: 将客户端的信息(进入了哪一个聊

Java网络编程TCP程序,服务器和客户机交互流程以及基本操作步骤。

1.什么是网络编程 网络编程其实就是实现两个计算机的数据交换(交互). 可以通过直接或间接的通过网络协议与其他的计算机进行通讯.(HTTP协议,TCP/IP协议等) 2.Tcp网络编程的实现流程 主要分为服务器端(Server)和客户端(Client). 通过这个图我们其实就可以了解了实现服务器和客户机交互过程是怎么样的了. 实现这些原理最重要的是Socket类也叫做套接字.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 服务器端 1.首先创建ServerSocket对象并

JAVA网络编程TCP通信

Socket简介: Socket称为"套接字",描述IP地址和端口.在Internet上的主机一般运行多个服务软件,同时提供几种服务,每种服务都打开一个Socket,并绑定在一个端口上,不同的端口对应于不同的服务.Socket和ServerSocket类位于java.net包中.ServerSocket用于服务端,Socket是建立网络连接时使用的.连接成功时,应用程序两端都会产生一个Socket实例,通过操作这个实例完成所需会话. Socket常用方法: -int getLocalP

Java网络编程のTCP/IP

TCP/IP参考模型和TCP/IP协议 与OSI参考模型相似,TCP/IP参考模型汲取了网络分层的思想,而且对网络的层次做了简化,并在网络各层都提供了完善的协议,这些协议构成了TCP/IP协议集,简称TCP/IP协议. TCP/IP参考模型分为4个层次:应用层.传输层.网络互连层和主机-网络层.在每一层都有相应的协议.确切地说,TCP/IP协议应该称为TCP/IP协议集,它是TCP/IP参考模型的除了主机-网络层(由第三方提供)以外的其他三层的协议的集合,而IP协议和TCP协议则是协议集中最核心

java网络编程(4)——udp实现聊天

UDP可以实现在线聊天功能,我这里就是简单模拟一下: 发送端: package com.seven.udp; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class CharByUpdSend implements

java网络编程TCP

图片来自网络 [服务端] import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; //服务端 public class MyServer { public static void main(String[] args) { ServerSocket serverSocket =

python 学习5 网络编程-TCP/UDP

摘抄自:廖雪峰的官方网站:http://www.liaoxuefeng.com/ TCP客户端和服务器端代码: #coding=utf-8 #客户端程序TCP 连接 import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('127.0.0.1',9999)) print(s.recv(1024)) for data in ['Michael','Tracy','Sarah']: s.send(data

linux网络编程--tcp/udp编程模型

tcp 模型如下: 上面的模型已经很清楚了 具体函数用法就不细说了 请看tcp简单的例子: 其中server.c #include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h> #define e