Java基础-网络编程(二)

来源:互联网 发布:单片机 usb 虚拟串口 编辑:程序博客网 时间:2024/06/05 17:56

一、简述:

在上一篇文章提到了网络编程的基础知识,今天将继续为大家介绍网络编程的基础知识,并提供相应的Demo。

二、TCP协议与UDP协议:

通过上一篇文章大家可以知道网络层主要协议是IP协议。而今天主要讲的是TCP和UDP协议以及简单的Demo。

TCP(Transfer Control Protocol)

一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport Layer)通信协议。

特点:

面向连接
点到点的通信
高可靠性
占用系统资源多、效率低

生活案例:

打电话

应用案例:

HTTP、FTP、TELNET、SMTP 等

UDP(User Datagram Protocol)

一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务

特点:

非面向连接,传输不可靠,可能丢失
发送方不管接收方是否准备好,是否收到也不确认
可以广播发送
非常简单的协议,开销小

生活案例:

电视与电视塔的关系

应用案例:

DNS、SNMP

三、常用的知识

InetAddress类:

封装计算机的IP地址,没有端口

//使用getLocalHost方法创建InetAddress对象InetAddress addr = InetAddress.getLocalHost();System.out.println(addr.getHostAddress());  //返回:192.168.1.110System.out.println(addr.getHostName());  //输出计算机名//根据域名得到InetAddress对象addr = InetAddress.getByName(“www.163.com”); System.out.println(addr.getHostAddress());  //返回 163服务器的ip:61.135.253.15System.out.println(addr.getHostName());  //输出:www.163.com//根据ip得到InetAddress对象addr = InetAddress.getByName(“61.135.253.15”); System.out.println(addr.getHostAddress());  //返回 163服务器的ip:61.135.253.15System.out.println(addr.getHostName());  //输出ip而不是域名。如果这个IP地 址不存在或DNS服务器不允许进行IP地址和域名的映射,getHostName方法就直接返回这个IP地址。

InetSocketAddress:

包含端口,用于socket通信的

//包含端口InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);InetSocketAddress socketAddress2 = new InetSocketAddress(“localhost”,9000);System.out.println(socketAddress.getHostName());System.out.println(socketAddress2.getAddress());

URL

统一资源定位符,由4部分组成:* 协议、存放资源的主机域名、端口号和资源文件名 *

URL是指向互联网“资源”的指针

资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

URL u = new URL("http://www.baidu.con:80/index.html#aa?cansu=bjsxt");System.out.println("获取与此url关联的协议的默认端口:"+u.getDefaultPort());System.out.println(“getFile:”+u.getFile());  //端口号后面的内容System.out.println("主机名:"+u.getHost());  //www.google.cnSystem.out.println(“路径:”+u.getPath());  //端口号后,参数前的内容System.out.println(“端口:”+u.getPort());  //存在返回80.否则返回-1System.out.println("协议:"+u.getProtocol()); System.out.println("参数部分:"+u.getQuery()); System.out.println("锚点:"+u.getRef()); URL u = new URL("http://www.abc.com/aa/");URL u2 = new URL(u,“2.html”);  //相对路径构建url对象System.out.println(u2.toString());  //http://www.abc.com/aa/2.html

四、套接字Socket

我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间,则是使用套接字来进行分离。

图一

套接字就像是传输层为应用层开的一个小口,应用程序通过这个小口向远程发送数据,或者接收远程发来的数据;而这个小口以内,也就是数据进入这个口之后,或者数据从这个口出来之前,是不知道也不需要知道的,也不会关心它如何传输,这属于网络其它层次的工作。

图二

Socket实际是网络传输层供给应用层的编程接口。传输层则在网络层的基础上提供进程到进程问的逻辑通道,而应用层的进程则利用传输层向另一台主机的某一进程通信。Socket就是应用层与传输层之间的桥梁。

图三

使用Socket编程可以开发客户机和服务器应用程序,可以在本地网络上进行通信,也可通过Internet在全球范围内通信。

图四

五、TCP编程

需求:完成网络登录功能:
用户输入用户名密码,服务器给出登录成功或失败的提示
分析

  • 1 使用基于TCP协议的Socket网络编程实现
  • 2 TCP协议基于请求-响应模式
  • 3 在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序
  • 4 第一次通讯中等待连接的程序被称作服务器端(Server)程序
  • 5 利用IO流实现数据的传输

图五

TCP通信原理(详细步骤)

  • 1 服务器创建ServerSocket,在指定端口监听并并处理请求。
  • 2 客户端创建Socket,向服务器发送请求。

图六

网络登录功能分解:

  • 1 单向:客户端向服务器端发送字符串,服务器获取字符串并输出
  • 2 双向:服务器端给出客户端反馈,客户端得到反馈并输出
  • 3 对象:客户端向服务器端发送User对象,服务器端获取对象并输出
  • 4 多线程:服务器接收多个客户端的请求,并给出反馈每个客户请求开启一个线程

代码实例:
在这里我只给出功能分解的第四步的源码了,大家一个根据第四步,一步一步向前练习。

实体类:

import java.io.Serializable;public class User implements Serializable{    private static final long serialVersionUID = 1809727215200397637L;    private String user;    private String password;    public User() {        super();    }    public User(String user, String password) {        super();        this.user = user;        this.password = password;    }    public String getUser() {        return user;    }    public void setUser(String user) {        this.user = user;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    @Override    public String toString() {        return "User [user=" + user + ", password=" + password + "]";    }}

服务端代码:

import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class TestServer {    @SuppressWarnings("resource")    public static void main(String[] args) throws IOException, ClassNotFoundException {        // 创建端口        ServerSocket serversocket = new ServerSocket(8888);        int i = 1;        while (true) {            // 使用serversocket进行监听            Socket socket = serversocket.accept();            new LoginThread(socket).start();            System.out.print("第"+i+"个用户访问,IP地址是:" + socket.getInetAddress().getHostAddress());            i++;        }        //socket.close();    }}

客户端代码:

import java.io.DataInputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;import java.util.Scanner;import com.fddqq.socket.Entity.User;public class TestClient {    public static void main(String[] args) throws UnknownHostException, IOException {        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);        Scanner input = new Scanner(System.in);        System.out.print("请输入用户名:");        String name = input.next();        System.out.print("请输入密码:");        String password = input.next();        User user = new User(name, password);        OutputStream os = socket.getOutputStream();        ObjectOutputStream oos = new ObjectOutputStream(os);        oos.writeObject(user);        DataInputStream dis = new DataInputStream(socket.getInputStream());        String result = dis.readUTF();        System.out.println("客户端输出:" + result);        input.close();        dis.close();        oos.close();        socket.close();    }}

模拟数据库验证密码:

import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.net.Socket;import com.fddqq.socket.Entity.User;public class LoginThread extends Thread {    private Socket socket;    public LoginThread() {        super();    }    public LoginThread(Socket socket) {        super();        this.socket = socket;    }    public Socket getSocket() {        return socket;    }    public void setSocket(Socket socket) {        this.socket = socket;    }    @Override    public void run() {        ObjectInputStream ois = null;        DataOutputStream dos = null;        try {            InputStream is;            is = socket.getInputStream();            ois = new ObjectInputStream(is);            User user = (User) ois.readObject();            System.out.println(",服务器端输出:" + user);            dos = new DataOutputStream(socket.getOutputStream());            if ("fddqq".equals(user.getUser()) && "123456".equals(user.getPassword())) {                String str = "登陆成功";                dos.writeUTF(str);            } else {                String str = "登陆失败";                dos.writeUTF(str);            }        } catch (IOException |                ClassNotFoundException e) {            e.printStackTrace();        } finally {            try {                dos.close();            } catch (IOException e) {                e.printStackTrace();            }            try {                ois.close();            } catch (IOException e) {                e.printStackTrace();            }            try {                socket.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

运行结果
先启动服务器端代码,然后在启动客户端代码:

登陆失败:

客户端:

图七

服务器端:

图八

登陆成功:

客户端:
图九
服务器端:

图十

总结:
服务器创建ServerSocket,在指定端口监听并并处理请求;客户端创建Socket,向服务器发送请求
ServletSocket通过accept() 接收用户请求并返回对应的Socket,否则一种处于监听等待状态,线程也被阻塞

客户端发送数据需要输出流(写),客户端获取反馈数据需要输入流(读)
服务端反馈数据需要输出流(写),服务端获取请求数据需要输入流(读)
一旦使用ServerSocket和Socket建立了网络连接后,网络通信和普通IO流操作并没有太大区别

网络通信输出流建议使用DataOutputStream和ObjectOutputStream,与平台无关,输入流相应使用DataIntputStream和ObjectInputStream
如果是字符串通信也可以使用BufferedReader和PrintWriter,简单方便

六、UDP编程

需求:完成在线咨询功能:
客户和咨询师在线交流

分析
使用基于UDP协议的Socket网络编程实现
不需要利用IO流实现数据的传输
每个数据发送单元被统一封装成数据包的方式,发送方将数据包发送到网络中,数据包在网络中去寻找他的目的地。

UDP基本概念
DatagramSocket:用于发送或接收数据包
DatagramPacket:数据包

代码实例

客户端:

import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import com.fddqq.socket.Entity.User;public class AskClient {    public static void main(String[] args) throws IOException {        DatagramSocket ds = new DatagramSocket(8888);         int num = 9;        double sum = 8.8;        String str = "奋斗的蛐蛐!";        User user = new User("奋斗的蛐蛐", "fddqq");        ByteArrayOutputStream baos = new ByteArrayOutputStream();        ObjectOutputStream oos = new ObjectOutputStream(baos);        oos.writeInt(num);        oos.writeDouble(sum);        oos.writeUTF(str);        oos.writeObject(user);        byte [] buf = baos.toByteArray();        DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 9999) ;        ds.send(packet);        ds.close();    }}

服务端:

import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.net.DatagramPacket;import java.net.DatagramSocket;public class AskServer {    public static void main(String[] args) throws IOException, ClassNotFoundException {        DatagramSocket ds = new DatagramSocket(9999);        byte [] buf = new byte[1024];        DatagramPacket packet = new DatagramPacket(buf, buf.length);        ds.receive(packet);        byte [] buf2 = packet.getData();        InputStream bais = new ByteArrayInputStream(buf2, 0, packet.getLength());        ObjectInputStream ois =new ObjectInputStream(bais);        System.out.println(ois.readInt());        System.out.println(ois.readDouble());        System.out.println(ois.readUTF());        System.out.println(ois.readObject());//      System.out.println(new String(packet.getData(),0,packet.getLength()));      //获取数据//      System.out.println(packet.getAddress());//获取对方IP//      System.out.println(packet.getPort());   //获取对方端口//      System.out.println(packet.getLength()); //获取数据长度        ds.close();    }}

运行结果

先运行服务器端,在运行客户端,然后会在服务器端输出下面的场景:

图十一

七、结束语

今天就写到这里,说一千道一万,看的再多,不如自己手敲一遍。如果大家感觉有收获,不妨作作下面的习题,如果又需要下面习题的源码的可以留言给我,我会私信给大家源码连接地址。

喜欢的话可以点个喜欢与关注,感谢大家支持,也欢迎有不同意见的童鞋指教。谢谢大家!

使用基于UDP的Java Socket编程,完成在线咨询功能:

  • 1 客户向咨询人员咨询。
  • 2 咨询人员给出回答。
  • 3 客户和咨询人员可以一直沟通,直到客户发送bye给咨询人员。
0 0
原创粉丝点击