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给咨询人员。
- Java基础—网络编程(二)
- Java基础-网络编程(二)
- java基础整理二十四(网络编程二)
- 网络编程基础(二)
- java基础整理二十三(网络编程)
- Java基础——网络编程(二)
- 网络编程基础<二>
- Java 网络编程(二)
- Java网络编程(二)
- java网络编程(二)
- Java基础(网络编程)
- Java笔记二十三.网络编程基础与UDP编程
- linux网络编程基础(二)
- 套接字网络编程基础(二)
- Linux网络编程基础(二)
- (1)Java网络编程----网络基础
- java学习笔记------java网络编程基础二
- 二.Java编程基础(二)
- Django 数据库错误
- 解决金山词霸2010牛津旗舰版破解词典丢失的方法
- for循环
- Struts1 NESTED标签
- SpringMVC创建web项目基础之(二)——Spring MVC与Mybatis整合详解
- Java基础-网络编程(二)
- windows 纤程(fiber) 实现的协程
- 网页下载器urllib2简介
- Problem 2 交错和查询
- Android-WindowManger的应用
- 汽车维修问题多 别被维修店潜规则忽悠了
- 关于Class.getResource和ClassLoader.getResource的路径问题
- java集合框架
- 2017.1.14——寒假集训第三天