一、网络编程三要素:
(一)IP地址:
Inetaddress:此类表示Internet协议(IP)地址
方法:
注解:
机器名:
例子:
package HMjavaSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemon01 {
public static void main(String[] args) {
try {
//InetAddress address = InetAddress.getByName("192.168.56.1");//IP
InetAddress address = InetAddress.getByName("LAPTOP-VNEU4A7U");//主机名就是你电脑上的机器名
String name = address.getHostName();//获取主机名
String ip = address.getHostAddress();//获取ip地址
System.out.println("主机名:"+name);
System.out.println("IP地址:"+ip);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
(二)端口:设备上应用程序的唯一标识
端口号:用两个字节表示的整数,它的取值范围是0~65535,其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另一个服务或者应用所占用,会导致当前程序启动失败(修改端口号即可)。
(三)协议:计算机网络中,连接和通信的规则被称为网络通信协议。
1)UDP是面向无连接的通讯协议
2)UDP数据包括目的端口号和源端口号信息
3)由于通讯不需要连接,所以可以实现广播发送,并不局限于端到端。
1)TCP是面向连接的通信协议
2)通过三次握手建立连接,通讯完成时要拆除连接
3)由于TCP是面向连接的所以只能用于端到端的通讯
二、UDP通信程序
(一)UDP通信原理:
(二)UDP发送数据:
发送数据的步骤:
1)创建发送端的Socket对象(DatagramSocket)
2)创建数据,并把数据打包(DatagramPacket)
3)调用DatagramSocket对象方法发送数据
4)关闭发送端
注意:
例子:
package HMjavaSocket;
import java.io.IOException;
import java.net.*;
public class SendDemo {
public static void main(String[] args) throws IOException {
//1、创建发送端的Socket对象(DatagramSocket)
//DatagramSocket()构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket ds = new DatagramSocket();
//2、创建数据,并把数据打包
//DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
byte[] bys = "hello,我来了".getBytes();
//int length = bys.length;
//InetAddress addresses = InetAddress.getByName("192.168.56.1");//通过网络来这个ip地址
//int port = 10086;
//DatagramPacket dp = new DatagramPacket(bys,length,addresses,port);
//可简写为:
DatagramPacket dp = new DatagramPacket(bys,bys.length,InetAddress.getByName("192.168.56.1"),10086);
//3、调用DatagramSocket对象的方法发送数据
// void send(DatagramPacket p) 从此套接字发送数据报包。
ds.send(dp);
//4、关闭发送端
ds.close();
}
}
(三)UDP接受数据:
1)创建接受端的Socket对象(DatagramSocket)
2)创建一个数据包(DatagramPacket),用于接受数据
3)调用DatagramSocket对象的方法接受数据
4)解析数据包、并把数据在控制台显示
5)关闭接受端
例子:
package HMjavaSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//1)创建接受端的Socket对象(DatagramSocket)
//DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。
DatagramSocket ds = new DatagramSocket(10086);
//2)创建一个数据包,用于接受数据
//DatagramPacket(byte[] buf, int length)构造 DatagramPacket,用来接收长度为 length 的数据包。
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//3)调用DatagramSocket对象的方法接受数据
ds.receive(dp);
//4)解析数据包、并把数据在控制台显示
byte[] datas = dp.getData();
String dataString = new String(datas);//将字节数组数据转换成字符串形式
System.out.println("数据是:"+dataString);
//4)关闭发送端
ds.close();
}
}
两个例子一起运行:
注意:要先运行接受端(ReceiveDemo),再运行发送端(SendDemo)
例子优化:
package HMjavaSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//1)创建接受端的Socket对象(DatagramSocket)
//DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。
DatagramSocket ds = new DatagramSocket(10086);
//2)创建一个数据包,用于接受数据
//DatagramPacket(byte[] buf, int length)构造 DatagramPacket,用来接收长度为 length 的数据包。
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//3)调用DatagramSocket对象的方法接受数据
ds.receive(dp);
//4)解析数据包、并把数据在控制台显示
//byte[] datas = dp.getData();
//int len = dp.getLength();//可以限定范围
//String dataString = new String(datas,0,len);//将字节数组数据转换成字符串形式
//System.out.println("数据是:"+dataString);
//可以优化为:
System.out.println("数据是:" + new String(dp.getData(),0,dp.getLength()));
//4)关闭发送端
ds.close();
}
}
(四)UDP通信程序练习:
客户端:
package HMjavaSocket.demoUDP;
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;
public class SendDemo {
public static void main(String[] args) throws IOException {
//创建发送端Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket();
//字节封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = br.readLine()) != null)
{
//输入数据是886,发送数据结束
if ("886".equals(line))
{
break;
}
//创建数据,并把数据打包
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys,bys.length, InetAddress.getByName("192.168.56.1"),12345);
//调用DatagraSocket对象的方法发送数据
ds.send(dp);
}
//关闭发送端
ds.close();
}
}
服务器端:
package HMjavaSocket.demoUDP;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/*
UDP接受数据:
因为接受端不知道发送端什么时候停止发送,故采用死循环接收
*/
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//创建接受端的Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket(12345);
while (true) {
//创建一个数据包,用于接受数据
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
//调用DatagramPacket对象的方法接受数据
ds.receive(dp);
//解析数据包,并把数据在控制台显示
System.out.println("数据是:" + new String(dp.getData(), 0, dp.getLength()));
}
//关闭接受端
//ds.close();
}
}
三、TCP通信程序
(一)TCP通信原理:
(二)TCP发送数据:
发送数据的步骤:
1)创建客户端的Socket对象(Socket)
Socket(String host,int port)
2)获取输出流,写数据 :OutputStresam.getOutputStream()
3)释放资源:void close()
代码:
package HMjavaSocket.DemoTCP;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//1)创建客户端Socket对象(Socket)
//Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
//Socket s = new Socket(InetAddress.getByName("192.168.56.1"),10000);
//Socket(String host, int port)创建一个流套接字并将其连接到指定主机上的指定端口号。可直接写ip地址
Socket s = new Socket("192.168.56.1",10000);
//2)获取输出流,写数据
//getOutputStream()返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我来了".getBytes());
//3)释放资源
os.close();
}
}
(三)TCP接受数据:
1)创建服务器端的Socket对象(ServerSocket)
2)监听客户端连接,返回一个Socket对象
Socket.accept()
3)获取输入流,读数据,并把数据显示在控制台
InputStream.getInputStream()
4)释放资源
void close()
注意:Address already in use: JVM_Bind(端口冲突,更改端口号即可)
例子:
服务端:
package HMjavaSocket.DemoTCP;
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 {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket ss = new ServerSocket(1000);
//Socket accept() 侦听并接受到此套接字的连接。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("数据是:"+data);
//释放资源
ss.close();
}
}
客户端:
package HMjavaSocket.DemoTCP;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//1)创建客户端Socket对象(Socket)
//Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
//Socket s = new Socket(InetAddress.getByName("192.168.56.1"),10000);
//Socket(String host, int port)创建一个流套接字并将其连接到指定主机上的指定端口号。可直接写ip地址
Socket s = new Socket("192.168.56.1",1000);
//2)获取输出流,写数据
//getOutputStream()返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我来了".getBytes());
//3)释放资源
s.close();
}
}
先要运行服务端,再运行客户端