一、网络编程的三要素
IP、端口号、协议。
特殊IP地址127.0.0.1,也可以是localhost,是回送地址也称回环地址,也称本机IP,永远只会寻找当前所在本机。
常见cmd命令:
ipconfig:查看本机IP地址;
ping:检查网络是否连通。格式为“ping <IP地址或网址>”,作用是查看本机与ping命令中IP地址指定的主机网络是否连通。
例如,查看本机IP地址:
例如,测试主机是否与百度服务器连通:
上图中的结果显示无数据包丢失,表示网络连通。
二、java中的InetAddress类(用来表示IP)
InetAddress类无构造方法,需要通过静态方法获取IP地址。
例如,通过IP地址获取InetAddress对象:
再例如,通过主机名获取InetAddress对象:
先查看本机的主机名。
使用InetAddress对象的方法:
注意:
getHostName()如果因为网络原因或者局域网中不存在这台电脑,则获取不到该主机名,方法的返回值可能为IP地址。
三、UDP协议发送和接收数据
1.UDP发送数据
步骤如下,可以使用寄快递的步骤来理解:
DatagramSocket对象的细节:
(1)DatagramSocket对象会绑定端口,通过这个端口往外发送数据;
(2)使用空参构造方法新建对象则在所有可用的端口中随机一个进行使用;
也可使用有参的构造方法新建对象指定端口号进行绑定。
例如,使用UDP发送数据如下:
public class MyApp {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象(快递公司)
DatagramSocket ds = new DatagramSocket();
String data = "你好!";
byte[] dataBytes = data.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
//端口号
int port = 10086;
//2.新建DatagramPacket对象打包数据(包裹)
DatagramPacket dp = new DatagramPacket(dataBytes,dataBytes.length,address,port);
//3.发送数据
ds.send(dp);
//4.释放资源
ds.close();
}
}
2.UDP接收数据
注意:接收时创建DataGramSocket对象时一定要绑定端口,而且要与发送的端口保持一致。
代码为:
public class ReceiveMessage {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象(快递公司)
DatagramSocket ds = new DatagramSocket(10086);
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);//如果接收不到数据receive()方法会阻塞
//3.解析数据包
byte[] data = dp.getData();
int len = dp.getLength();
InetAddress address= dp.getAddress();
int port =dp.getPort();
System.out.println("接收到数据"+new String(data,0,len));
System.out.println("该数据是从"+address+"这台电脑中的"+port+"端口中发出的");
//4.释放资源
ds.close();
}
}
之后,先运行接收端程序,再运行发送端程序,结果如下:
可以看出发送端口随机选择为63783。
补充,若要同时启动多个发送端程序,方法如下:
(1)选择IDEA的右上角,选择"Edit Configurations":
(2)选择类名,点击“Modify options”,选择“Allow Multiple Instances":
结果为:
点击OK按钮。
这样就可以同时运行多个接收端程序:
注意把接收端的端口号去掉,令其随机获得一个端口号,否则端口冲突会报错。
四、TCP协议
TCP协议通信之前要保证连接已经建立,在通信的两端各建立一个Socket对象,通过Socket产生IO流来进行网络通信。
代码实现如下:
客户端。
public class Client {
public static void main(String[] args) throws IOException {
//1.创建Socket对象,在创建对象的时候同时会连接服务端(这里是127.0.0.1:10000),如果连不上代码会报错
Socket socket = new Socket("127.0.0.1",10000);
//2.可以从连接通道中获取输出流
OutputStream os = socket.getOutputStream();
//写出数据
os.write("aaa".getBytes());
//3.释放资源
os.close();
socket.close();
}
}
服务器端。
public class Server{
public static void main(String[] args) throws IOException {
//1.创建对象
ServerSocket ss = new ServerSocket(10000);
//监听客户端的连接
Socket socket = ss.accept();
//3.从连接通道中获取输入流读取数据
InputStream is = socket.getInputStream();
int b;
while((b=is.read())!=-1){
System.out.println((char)b);
}
//4.释放资源
socket.close();
ss.close();
}
}
先运行服务器端,再运行客户端,效果如下:
注意,发送中文数据时会出现乱码的情况:
原因:“你好”.getBytes()使用的是默认的GBK编码方法,二在Server的socket.getInputStream中使用的是字节流的读取方式,一次读一个字节,再转成char就会乱码。
使用转换流读取数据: