——- android培训、java培训、期待与您交流! ———-
一、基本概念:
1、 两台主机间进行通信,步骤遵循以下几条:
1) 找到对方的IP地址
2) 数据发送到对方指定的应用程序上,为了标识这个程序,引进了端口号
3) 定义了通信规则(所谓的协议)。国家组织定义了通用的协议:TCP/IP协议
2、 网络模型
OSI参考模型和TCP/IP参考模型的对比
应用层上的协议: 端口号
1) http: 超文本传输协议(明文) 80
2) https: 超文本传输协议(在http基础上做了加密技术) 80
3) ftp: 文件传输协议(支持上传和下载) 20,21
4) DNS:域名解析协议(域名--IP地址访问指定位置) 53
5) SMTP: 简单邮件传输协议(发邮件) 25
6) POP3: 邮局协议(接邮件) 110
7) DHCP: 动态主机地址分配协议 67,68
8) telnet:远程登录 23
3、 IP地址:(InetAddress)
1) 网络中设备的标识
2) 不易记忆,可用主机名
3) 本地回环地址:127.0.0.1(主机地址) 主机名:localhost
4)InetAddress的方法:构造方法私有,不能直接创建对象。
InetAddress getByName(String host):在给定主机名的情况下确定主机的ip地址。
InetAddress getLocalHost():返回本地主机。
InetAddress[] getAllByName(String host)
ip.getHostAddress(),
ip.getHostName()
第四位IP地址为0是网络地址
第四位IP地址为255是广播地址
4、 端口号:
用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口。
5、 传输协议:
通讯的规则
常见协议:TCP/UDP
6、 TCP和UDP的区别:
1、 UDP:(类似保安手中的步话机)
1) 将数据的源和目的封装成数据包,不需要建立连接
2) 每个数据报的大小在限制在64k内。
3) 因无连接,是不可靠协议。
4) 不需要建立连接,速度快。
5) 应用案例:QQ、FeiQ聊天、桌面共享、在线视频用的都是UDP传输协议。
2、 TCP:(类似打电话)
1) 建立连接,形成传输数据的通道。
2) 在连接中进行大数据量传输。
3) 通过三次握手完成连接,是可靠协议
4) 必须建立连接,效率会降低。
7、 Socket套接字
1) 网络编程其实就是Socket编程
2) Socket就是为网络服务提供的一种机制
通信的两端都是Socket
网络通信其实就是Socket通信
数据在两个Socket间通过IO传输
3) Socket是一个通信的端点,它是应用程序用来在网络上发送或接收数据包的对象
4) 可用的Socket类型有两种:
流式套接字:确保数据以正确的顺序无重复地被送达
基于TCP协议的网络编程使用的就是流式套接字
数据报套节字:不能确保数据能被送达,不能确保发送的顺序
基于UDP协议的网络编程使用的就是数据报套接字
二、基于UDP协议的网络编程——-发送端和接收端
1、java.net包中提供了DatagramSocket、DatagramPacket类用来支持UDP协议的网络编程
2、发送时的思路:(步骤)
1)建立UDPSocket服务
2)提供数据,并将数据封装到数据包中
3)通过Socket服务的发送功能,将数据包发出去
4)关闭资源
示例演示:通过UDP传输方式,将一段数据发送出去
package com.tcpudplianxi;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**需求:通过UDP传输方式,将一段数据发送出去
* @param args
*/
public class UDPsend {
public static void main(String[] args) throws IOException {
//1)建立UDPSocket服务
DatagramSocket ds=new DatagramSocket();
//2)提供数据,并将数据封装到数据包中
byte[] buf="UDP 发送端来了".getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10000);
//3)通过Socket服务的发送功能,将数据包发出去
ds.send(dp);
//4)关闭资源
ds.close();
}
}
3、接收时的思路:(步骤)
1)定义UDPSocket服务,通常会监听一个端口。
2)定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提高字节数据中的不同数据信息。
3)通过Socket服务的receive方法将收到的数据存入已定义好的数据包中。
4)通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上
5)关闭资源。
示例演示:定义一个应用程序,用于接收UDP协议传输的数据,并处理。
package com.tcpudplianxi;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**需求:定义一个应用程序,用于接收UDP协议传输的数据,并处理。
* @param args
*/
public class UDPreceive {
public static void main(String[] args) throws IOException {
//1)建立UDPSocket服务,建立端口。
DatagramSocket ds=new DatagramSocket(10000);
//2)定义一个数据包,用于存储接收到的字节数据
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//3)通过Socket服务的receive方法将收到的数据存入已定义好的数据包中。
ds.receive(dp);
//4)通过数据包对象的方法获取其中的数据
String ip=dp.getAddress().getHostAddress();
String data=new String(dp.getData(),0,dp.getLength());
int port=dp.getPort();
System.out.println(ip+"...."+data+"...."+port);
//5)关闭资源。
ds.close();
}
}
4、 练习一:UDP—键盘录入数据方式来进行数据传输
发送端代码:
package com.tcpudplianxi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**需求:UDP---键盘录入数据方式来进行数据传输(发送端)
* @param args
*/
public class lianxi01 {
public static void main(String[] args) throws SocketException,IOException {
//创建UDP的socket服务
DatagramSocket ds=new DatagramSocket();
//键盘输入数据
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
//读取输入的数据
String line=null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
//把数据封装进数据包
byte[] buf=line.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10005);
//发送数据
ds.send(dp);
//关闭资源
ds.close();
}
}
}
接收端代码:
package com.tcpudplianxi;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**需求:UDP---键盘录入数据方式来进行数据传输(接收端)
* @param args
*/
public class lianxi01receive {
public static void main(String[] args) throws SocketException,IOException {
//创建socket服务,建立端点连接
DatagramSocket ds=new DatagramSocket(10005);
while(true)
{
//定义数据包,存储数据
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//接收数据
ds.receive(dp);
//获取数据包中的数据
String ip=dp.getAddress().getHostAddress();
String data=new String(dp.getData(),0,dp.getLength());
System.out.println(ip+"...."+data);
//关闭资源
ds.close();
}
}
}
5、 练习二:用UDP编写一个聊天程序
package com.tcpudplianxi;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**需求::用UDP编写一个聊天程序
* @param args
*
* 思路:有收数据的部分和发数据的部分,这两部分需要同时进行,这就需要用到多线程技术。一个线程控制收,一个线程控制发。
* 因为收和发动作是不一致的,所以要定义两个run方法,这两个方法要封装到不同的类中。
*/
public class lianxi02 {
public static void main(String[] args) throws SocketException {
DatagramSocket sendSocket=new DatagramSocket();
DatagramSocket receiveSocket=new DatagramSocket();
new Thread(new Send(sendSocket)).start();
new Thread(new Receive(receiveSocket)).start();
}
}
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds=ds;
}
public void run()
{
try
{
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
byte[] buf=new byte[1024];
DatagramPacket dp=newDatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10007);
ds.send(dp);
}
}
catch(Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}
class Receive implements Runnable
{
private DatagramSocket ds;
public Receive(DatagramSocket ds)
{
this.ds=ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip=dp.getAddress().getHostAddress();
String data= new String(dp.getData(),0,dp.getLength());
System.out.println(ip+"::"+data);
}
}
catch(Exception e)
{
throw new RuntimeException("接收数据失败!");
}
}
}