1 网络要素(IP地址、端口号、传输协议)
IP地址:InetAddress
网络中设备的标识
不易记忆,可用主机名
本地回环地址:127.0.0.1 主机名:localhost
端口号:
用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口。
传输协议:通讯的规则常见协议:TCP,UDP
UDP
将数据及源和目的封装成数据包中,不需要建立连接
每个数据报的大小在限制在64k内
因无连接,是不可靠协议
不需要建立连接,速度快
TCP(传输控制协议)
建立连接,形成传输数据的通道。
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低
2 IP对象 InetAddress
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IPDemo {
public static void main(String[] args) throws UnknownHostException {
//UnknownHostException未知主机异常
//获取本地主机ip地址对象
InetAddress ip = InetAddress.getLocalHost();
System.out.println(ip.getHostName()+":"+ip.getHostAddress());
//获取其他主机的ip地址对象
ip = InetAddress.getByName("www.baidu.com");
//获取主机ip地址
System.out.println(ip.getHostAddress());
//获取主机名
System.out.println(ip.getHostName());
}
}
域名解析:
就是通过主机名(域名或者网址),在DNS服务器(域名解析服务器)中找到相应的ip地址,返回,最终才能访问所指定的网址 通常由宽带服务商指定DNS服务器
3 TCP协议
客户端发数据到服务端
Tcp传输,客户端建立的过程:
1、创建tcp客户端socket服务。使用的是Socket对象。建议该对象一创建就明确目的地。要连接的主机。
2、如果连接建立成功,说明数据传输通道已建立。该通道就是socket流 ,是底层建立好的。 既然是流,说明这里既有输入,又有输出。想要输入或者输出流对象,可以找Socket来获取。 可以通过getOutputStream(),和getInputStream()来获取两个字节流。
3、使用输出流,将数据写出。
4、关闭资源。
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo {
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端socket服务。
Socket socket = new Socket("127.0.0.1",10002);
//获取socket流中的输出流。
OutputStream out = socket.getOutputStream();
//使用输出流将指定的数据写出去。
out.write("tcp演示:哥们又来了!".getBytes());
//关闭资源。
socket.close();
}
}
服务端接收客户端发送过来的数据,并打印在控制台上。
建立tcp服务端的思路:
1、创建服务端socket服务。通过ServerSocket对象。
2、服务端必须对外提供一个端口,否则客户端无法连接。
3、获取连接过来的客户端对象。
4、通过客户端对象获取socket流读取客户端发来的数据 并打印在控制台上。
5、关闭资源。关客户端,关服务端。
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1创建服务端对象。
ServerSocket ss = new ServerSocket(10002);
//2,获取连接过来的客户端对象。
Socket s = ss.accept();//阻塞式.
String ip = s.getInetAddress().getHostAddress();
//3,通过socket对象获取输入流,要读取客户端发来的数据
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf,0,len);
System.out.println(ip+":"+text);
s.close();
ss.close();
}
}
4 UDP协议
创建UDP传输的发送端 :
1、建立udp的socket服务
2、将要发送的数据封装到数据包中
3、通过udp的socket服务 将数据包发送出去
4、关闭socket服务(因为调用了系统的底层资源网卡)
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSendDemo {
public static void main(String[] args) throws IOException {
System.out.println("发送端启动.......");
//1.udp的socket服务,使用DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
//2.将要发送的数据封装到数据包中
String str = "哥们来啦!";
//使用DatagramPacket将数据封装到该对象包中
byte[] buf = str.getBytes();
DatagramPacket dp =
new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
//通过udp的socket服务将数据包发送出去,使用send方法
ds.send(dp);
//关闭资源
ds.close();
}
}
建立UDP接收端:
1、建立udp socket服务,因为要接受数据,所以必须要明确端口号
2、创建数据包,用于存储接收到的数据,方便用于数据包对象的方法解析这些数据
3、使用socket服务的receive方法将接收到的数据存储到数据包中,
4、通过数据包的方法解析数据包中的数据
5、关闭资源
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceiveDemo {
public static void main(String[] args) throws IOException {
System.out.println("接收端启动.......");
//1.建立udp socket服务
DatagramSocket ds = new DatagramSocket(10000);
//2.创建数据包,用于存儲接受到到的数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//3.使用接收方法将数据存储在数据包中
ds.receive(dp);//阻塞式的方法,没有数据会等待
//4.通过数据包对象的方法,解析其中的数据,比如:地址,端口,数据内容
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port+":"+text);
//5.关闭资源
ds.close();
}
}
5 UDP协议练习-聊天程序
发送端:(将数据源改为键盘录入)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSendDemo {
public static void main(String[] args) throws IOException {
System.out.println("发送端启动.......");
//1.udp的socket服务,使用DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
//2.将要发送的数据封装到数据包中
//使用DatagramPacket将数据封装到该对象包中
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine())!=null){
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
ds.send(dp);
if("over".equals(line))
break;
}
ds.close();
}
}
接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceiveDemo {
public static void main(String[] args) throws IOException {
System.out.println("接收端启动.......");
//1.建立udp socket服务
DatagramSocket ds = new DatagramSocket(10000);
while(true){
//2.创建数据包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//3.使用接收方法将数据存储在数据包中
ds.receive(dp);
//4.通过数据包对象的方法,解析其中的数据,比如:地址,端口,数据内容
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port+":"+text);
}
//5.关闭资源
//ds.close();
}
}
基于多线程的聊天程序:
Send.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Send implements Runnable {
private DatagramSocket ds;
public Send(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
try {
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=bufr.readLine())!=null){
byte[] buf = line.getBytes();
DatagramPacket dp =
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10001);
ds.send(dp);
if("886".equals(line))
break;
}
ds.close();
} catch (Exception e) {
}
}
}
Rece.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Rece implements Runnable {
private DatagramSocket ds;
public Rece(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
while (true) {
// 2,创建数据包。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
// 3,使用接收方法将数据存储到数据包中。
ds.receive(dp);// 阻塞式的。
// 4,通过数据包对象的方法,解析其中的数据,比如,地址,端口,数据内容。
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(), 0, dp.getLength());
System.out.println(ip + "::" + text);
if(text.equals("886")){
System.out.println(ip+"....退出聊天室");
}
}
} catch (Exception e) {
}
}
}
ChatDemo.java
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ChatDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
DatagramSocket send = new DatagramSocket();
DatagramSocket rece = new DatagramSocket(10001);
new Thread(new Send(send)).start();
new Thread(new Rece(rece)).start();
}
}