网络编程
1. 网络编程三要素
- IP地址
IP地址是一个标识号,是设备的标识。通过这个标识号来指定要接收数据的计算机和识别发送的计算机。
- 端口
端口号可以唯一标识设备中的应用程序,也就是应用程序的标识。
- 协议
在计算机网络中,这些链连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守。常见的协议有UDP协议和TCP协议。
2. IP地址
(1)常用命令:
- ipconfig:查看本机IP地址
- ping IP地址:检查网络是否连通
(2)特殊IP地址:
- 127.0.0.1:是回送地址,可以代表本机地址,一般用来测试使用
3. InetAddress的使用
InetAddress:此类表示Internet协议(IP)地址
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// InetAddress address = InetAddress.getByName("LAPTOP-MHEG7I03");
InetAddress address = InetAddress.getByName("192.168.0.10");
String hostAddress = address.getHostAddress();
String hostName = address.getHostName();
System.out.println(hostAddress);
System.out.println(hostName);
}
}
4. 端口
端口:设备上应用程序的唯一标识
端口号:用两个字节表示的整数(0-65535),0-1023之间的端口用于一些知名的网站服务和应用。
5. 协议
协议:计算机网络中,连接和通信的规则被称为网络通信协议
(1)UDP协议
- 用户数据协议
- UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。发送端不管接收端是否存在,接收端也不会反馈是否收到数据
- 消耗资源小,通信效率高,通常用于音频、视频的传输
- 在传输重要数据时不建议使用UDP协议
(2)TCP协议
- 传输控制协议
- TCP协议是面向连接的通信协议,即传输新数据之前,在发送端和接收端建立逻辑联系,然后传输数据,它提供了两台计算机之间的可靠无差错的数据传输。
- 三次握手(面试常见题):在发送数据的准备阶段,客户端和服务端之间的三次交互,以保证连接的可靠
- 完成三次握手之后,客户端和服务端就可以开始进行数据传输了。TCP协议可以保证传输数据的安全。
5.1 UDP通信程序
(1)UDP发送数据
- 创建发送端的Socket对象
DatagramSocket()
- 创建数据包,并把数据打包
DatagramPacket(byte[] buf,int length,InetAddress address,int port)
-
调用DatagramSocket对象的方法发送数据
void send(DatagramPacke p)
-
关闭发送端
void close()
public class DatagramSocketDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
byte[] b="hello,world".getBytes();
DatagramPacket dp=new DatagramPacket(b,b.length,InetAddress.getByName("192.168.0.10"),10086);
ds.send(dp);
ds.close();
}
}
(2)UDP接收数据
- 创建接收端的Socket对象
DatagramSocket(int port)
- 创建数据包,用于接收数据
DatagramPacket(byte[] buf,int length)
-
调用DatagramSocket对象的方法接收数据
void receive(DatagramPacke p)
-
解析数据包,并把数据在控制台显示
byte[] getData()
int getLength()
- 关闭发送端
void close()
public class DatagramSockeReceivetDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds=new DatagramSocket(10086);
byte[] b=new byte[1024];
DatagramPacket dp=new DatagramPacket(b,b.length);
ds.receive(dp);
byte[] data = dp.getData();
String s = new String(data,0,dp.getLength());
System.out.println(s);
}
}
5.2 TCP通信程序
(1)TCP发送数据
-
创建客户端的Socket对象
Socket(String host,int port)
-
获取输出流,写数据
OutputStream getOutputStream()
-
释放资源
void close()
public class SendDemo { public static void main(String[] args) throws IOException { Socket s=new Socket("192.168.0.10",10086); OutputStream os = s.getOutputStream(); os.write("hello,world,我来了".getBytes()); s.close(); } }
(2)TCP接收数据
-
创建服务端 的Socket对象
ServerSocket(int port)
-
监听客户端连接,返回一个Socket对象
Socket accept()
-
获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
-
释放资源
void close()
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10086);
Socket s = ss.accept();
InputStream is = s.getInputStream();
byte[] b=new byte[1024];
int len = is.read(b);
String data=new String(b,0,len);
System.out.println(data);
s.close();
ss.close();
}
}
注意:
- 如果输入的端口已经被占用,则会报错,换一个端口就行
- 客户端和服务端的端口必须一致
练习1:客户端输入数据上传到服务端
(1)客户端
public class SendDemo02 {
public static void main(String[] args) throws IOException {
Socket s=new Socket("192.168.0.10",10086);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line=br.readLine())!=null){
if(line.equals("886")){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
}
}
(2)服务端
public class RerverDemo02 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10086);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
ss.close();
}
}
练习2:客户端:数据来自文本文件,客户接收反馈;服务端:接收数据写入文本文件,发送反馈,为每个客户开启一个线程
(1)客户端
public class SendDemo03 {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("B:\\车协\\前骑总结.txt")));
Socket s=new Socket("192.168.0.10",10086);
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
s.shutdownOutput();
//接收反馈
BufferedReader brserver = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(brserver.readLine());
br.close();
s.close();
}
}
(2)服务端
public class ReceiveDemo03 {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10086);
while (true){
Socket s = ss.accept();
new Thread(new ThreadServer (s)).start();
}
}
}
(3)ThreadServer类
public class ThreadServer implements Runnable {
private Socket s;
public ThreadServer() {
}
public ThreadServer(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
// BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\IDEA2019.2\\程序\\网络编程\\前骑总结copy.txt")));
int count=0;
File f=new File("D:\\IDEA2019.2\\程序\\网络编程\\前骑总结copy["+count+"].txt");
while (f.exists()){
count++;
f=new File("D:\\IDEA2019.2\\程序\\网络编程\\前骑总结copy["+count+"].txt");
}
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
String line;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//给出反馈
BufferedWriter bwSend=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwSend.write("文件上传成功");
bwSend.newLine();
bwSend.flush();
s.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结束发送数据的方法:(1)自定义结束标记;(2)使用shutdownOutput()方法(推荐)