学了java这么久了,还是老是忘记,所以这次又重新整理一遍笔记,希望对大家也有帮助
网络编程
在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换
网络编程三要素
IP地址
IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异
要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数
据的计算机和识别发送的计算机,而IP地址就是这个标识号。也就是设备的标识
ip地址的分类
每一个IP地址包括两部分:网络地址和主机地址。IP地址通常由点分十进制(例如:192.168.1.1)的方式来表示,IP地址要和子网掩码(用来区分网络位和主机位)配合使用。
注意事项:
每一个字节都为0的地址(“0.0.0.0”)对应于当前主机。
IP地址中的每一个字节都为1的IP地址(“255.255.255.255”)
是当前子网的广播地址。
IP地址中凡是以“1111”开头的E类IP地址都保留用于将来和实验使用。
IP地址中不能以十进制“127”作为开头,该类地址中数字127.0.0.1到
127.255.255.255用于回路测试,如:127.0.0.1可以代表本机IP地址,
用 http://127.0.0.1 就可以测试本机中配置的Web服务器网络ID的第一
个8位组也不能全置为“0”,全“0”表示本地网络
DOS常用命令:
ipconfig:查看本机IP地址
ping IP地址:检查网络是否连通
特殊IP地址:
127.0.0.1:是回送地址,可以代表本机地址,一般用来测试使用
端口
端口号
端口是通过端口号来标记的,端口号只有整数,范围是从0到65535.端口号不是随意使用的,而是按照一定的规定进行分配
知名端口号
知名端口是众所周知的端口号,范围从0到1023,以理解为,一些常用的功能使用的号码是估计的,好比 电话号码110、10086、10010一样。一般情况下,如果一个程序需要使用知名端口的需要有root权限。
动态端口号
动态端口的范围是从1024到65535
之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。
动态分配是指当一个系统程序或应用程序程序需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。
当这个程序关闭时,同时也就释放了所占用的端口号
常用端口:
mysql:3306
sqlserver:1433
oracle:1521
tomcat:8080
浏览器:80
协议
通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定
的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则
被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守
才能完成数据交换。常见的协议有UDP协议和TCP协议
InetAddress类
InetAddress:此类表示Internet协议(IP)地址
相关方法
方法名 | 说明 |
---|---|
static InetAddress getByName(Stringhost) | 确定主机名称的IP地址。主机名称可以是器名称,也可以是IP地址 |
String getHostName() | 获取此IP地址的主机名 |
String getHostAddress() | 返回文本显示中的IP地址字符串 |
import java.net.InetAddress;
import java.net.UnknownHostException;
public class l1 {
public static void main(String[] args) throws UnknownHostException {
InetAddress address = InetAddress.getByName("192.168.11.103");
//public String getHostAddress():返回文本显示中的IP地址字符串
String hostAddress = address.getHostAddress(); //192.168.11.103
//public String getHostName():获取此IP地址的主机名
String hostName = address.getHostName(); //DESKTOP-J91LIML
System.out.println(hostAddress+" "+hostName);
}
}
UDP协议
用户数据报协议(User Datagram Protocol)
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
例如视频会议通常采用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议
UDP通信程序
Java中的UDP通信
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
Java提供了DatagramSocket类作为基于UDP协议的Socket
构造方法
方法名 | 说明 |
---|---|
DatagramSocket() | 创建数据报套接字并将其绑定到本机地址上的任何可用端口 |
DatagramSocket(int port) | 构造数据报套接字并将其绑定到本地主机上的指定端口 |
DatagramPacket(byte[] buf,int len,InetAddressadd,int port) | 创建数据包,发送长度为le的数据包到指定主机的指定端口 |
DatagramPacket(byte[] buf, int len) | 创建一个DatagramPacket用于接收长度为len的数据包 |
相关方法
方法名 | 说明 |
---|---|
void send(DatagramPacket p) | 发送数据报包 |
void close() | 关闭数据报套接字 |
void receive(DatagramPacket p) | 从此套接字接受数据报包 |
发送数据的步骤
创建发送端的Socket对象(DatagramSocket)
创建数据,并把数据打包
调用DatagramSocket对象的方法发送数据
关闭发送端
udp发送数据
import java.io.IOException;
import java.net.*;
public class udp {
public static void main(String[] args) throws IOException {
// DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口
DatagramSocket ds = new DatagramSocket();
byte[] bytes = "dyk666".getBytes();
//创建数据,并把数据打包
//DatagramPacket(byte[] buf, int length, InetAddress address, int port)
//构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
DatagramPacket dp=new DatagramPacket(bytes,bytes.length, InetAddress.getByName("127.0.0.1"),10086);
//调用DatagramSocket对象的方法发送数据
ds.send(dp);
//关闭发送端
ds.close();
}
}
udp接收数据
接收数据的步骤
创建接收端的Socket对象(DatagramSocket)
创建一个数据包,用于接收数据
调用DatagramSocket对象的方法接收数据
解析数据包,并把数据在控制台显示
关闭接收端
解析数据包的方法
方法名 | 说明 |
---|---|
byte[] getData() | 返回数据缓冲区 |
int getLength() | 返回要发送的数据的长度或接收的数据的长度 |
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class udpr {
public static void main(String[] args) throws IOException {
//创建接收端的Socket对象(DatagramSocket)
DatagramSocket ds=new DatagramSocket(10086);
while (true)
{
//创建一个数据包,用于接收数据
byte[] bys=new byte[1024];
DatagramPacket dp=new DatagramPacket(bys,bys.length);
ds.receive(dp);
System.out.println("接收到的数据是:"+new String(dp.getData(),0,dp.getLength()));
}
}
}
TCP通信程序
TCP(Transmission Control Protocol)传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议
Java中的TCP通信
Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过
Socket产生IO流来进行网络通信。
Java为客户端提供了Socket类,为服务器端提供了ServerSocket类
构造方法
方法名 | 说明 |
---|---|
Socket(InetAddress address,int port) | 创建流套接字并将其连接到指定IP指定端口号 |
Socket(String host, int port) | 创建流套接字并将其连接到指定主机上的指定端口号 |
方法名 | 说明 |
---|---|
ServletSocket(int port) | 创建绑定到指定端口的服务器套接字 |
相关方法
方法名 | 说明 |
---|---|
InputStream getInputStream() | 返回此套接字的输入流 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
方法名 | 说明 |
---|---|
Socket accept() | 监听要连接到此的套接字并接受它 |
TCP发送数据
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class tcps {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(Socket)
Socket s=new Socket("127.0.0.1",10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流
OutputStream outputStream = s.getOutputStream();
byte[] bytes = "dyk666".getBytes();
outputStream.write(bytes);
s.close();
}
}
TCP接收数据
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class tcpr {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket对象(ServerSocket)
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字
ServerSocket ss=new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys=new byte[1024];
int len;
while((len=is.read(bys))!=-1){
String data=new String(bys,0,len);
System.out.println(data);
}
ss.close();
s.close();
}
}
注意,在运行tcp程序时,一定要先运行服务器,后运行客户端,不然会报错误 java.net.ConnectException: Connection refused: connect
tcp上传文件
客户端:数据来自于文本文件,接收服务器反馈
服务器:接收到的数据写入文本文件,给出反馈
由于读数据的方法是阻塞式的,服务器读数据的时候如果读不到数据会出现一直等待的现象,而导致程序卡死在哪
所以socket提供了方法来作为结束的标记,当读到此标记时会自动结束
方法名 | 说明 |
---|---|
void shutdownInput() | 将此套接字的输入流放置在“流的末尾” |
void shutdownOutput() | 禁止用此套接字的输出流 |
客户端
import java.io.*;
import java.net.Socket;
public class tcps {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(Socket)
Socket s=new Socket("127.0.0.1",10086);
//封装文本文件的数据
BufferedReader br=new BufferedReader(new FileReader("D:\\iotest\\dyk3.txt"));
//封装输出流写数据
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while((line=br.readLine())!=null)
{
bw.write(line);
bw.newLine();
bw.flush();
}
//public void shutdownOutput()
s.shutdownOutput();
//接收反馈
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(s.getInputStream()));
String data=bufferedReader.readLine();
System.out.println("服务器说: "+data);
bufferedReader.close();
br.close();
bw.close();
s.close();
}
}
服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class tcpr {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket对象(ServerSocket)
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字
ServerSocket ss=new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它
Socket s = ss.accept();
//接收数据
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw=new BufferedWriter(new FileWriter("123.txt"));
String line;
while ((line=br.readLine())!=null)
{
bw.write(line);
bw.newLine();
bw.flush();
}
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bufferedWriter.write("文件上传成功");
bufferedWriter.newLine();
bufferedWriter.flush();
ss.close();
bw.close();
}
}