网络编程
端口号是用两个字节(16位的二进制数)表示的,它的取值范围是0~65535,其中,0~1023之间的端口号用于一些知名的网络服务和应用,用户的普通应用程序需要使用1024以上的端口号,从而避免端口号被另外一个应用或服务所占用。
package com.igeek_01;
/**
* @author Lynn
* @create 2020-12-16-10:20
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 凡是.net包下的内容都是关于网络的api
*/
public class IPDemo {
public static void main(String[] args) throws UnknownHostException {
//获取本地IP地址
InetAddress localhost=InetAddress.getLocalHost();
System.out.println(localhost);//Lynn/192.168.2.184
//获取字符串类型的IP
String hostname=localhost.getHostName();
System.out.println(hostname);//Lynn
String hostAddress=localhost.getHostAddress();
System.out.println(hostAddress);//192.168.2.184
//获取其他IP地址
InetAddress byName=InetAddress.getByName("Lynn");
System.out.println(byName);//Lynn/192.168.2.184
}
}
UDP
发送和接收均可以使用的Socket类:
DatagramSocket
数据打包的相关类:
DatagramPacket
- 使用UDP接收数据的步骤:
1、建立接收端;
public DatagramSocket(int port): 指定程序端口号,方便发送端寻找
2、建立数据包,用于接收数据;
public DatagramPacket(byte[] buf, int length)
3、调用Socket的接收方法;
4、解析数据 ;
public byte[] getData(): 获取数据报包中的数据
public int getLength(): 获取数据报包中的数据长度
public InetAddress getAddress(): 获取发送方的IP
public int getPort(): 获取发送方的端口号
5、关闭Socket。
案例1
```java package com.igeek_02;
import java.io.IOException; import java.net.*;
/**
- UDP是一个传输协议 *
当前的服务器端用于接收数据 */ public class UDPService { public static void main(String[] args) throws IOException {
//建立连接
DatagramSocket ds=new DatagramSocket(123);
//建立数据包,用于接收数据
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes, bytes.length);
//调用socket方法接收数据
ds.receive(dp);
//解析数据--针对数据包进行解析
InetAddress sendAddress=dp.getAddress();
String sendIP=sendAddress.getHostAddress();
int sendPort=dp.getPort();//端口号
//获取数据包中的数据
byte[] data=dp.getData();
int length=dp.getLength();
//将字节数组转换成字符串--String的构造函数
String s = new String(data, 0, length);
//输出
System.out.println("接收到来自"+sendIP+"的,端口号为"+sendPort+"的数据"+ s);
//关闭
ds.close();
} }
/**
- @author Lynn
- @create 2020-12-16-11:21 */
import java.net.*;
/**
发送端 */ public class UDPSend { public static void main(String[] args) throws Exception, UnknownHostException {
//建立连接
DatagramSocket ds=new DatagramSocket();
//创建数据
String s="I Love Java";
//数据打包
byte[] data=s.getBytes();//将字符串转化为字节数组
int length= data.length;
InetAddress address=InetAddress.getByName("192.168.2.184");
int port=123;//必须与接收端的一致
DatagramPacket dp=new DatagramPacket(data,length,address,port);
//调用方法进行发送
ds.send(dp);
//关闭连接
ds.close();
案例2
```java package com.igeek_03;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
/**
- UDP是一个传输协议 *
当前的服务器端用于循环接收数据 */ public class UDPService { public static void main(String[] args) throws IOException {
//建立连接
DatagramSocket ds=new DatagramSocket(123);
//反复接收数据
while (true){
//建立数据包,用于接收数据
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes, bytes.length);
//调用socket方法接收数据
ds.receive(dp);
//解析数据--针对数据包进行解析
InetAddress sendAddress=dp.getAddress();
String sendIP=sendAddress.getHostAddress();
int sendPort=dp.getPort();//端口号
//获取数据包中的数据
byte[] data=dp.getData();
int length=dp.getLength();
//将字节数组转换成字符串--String的构造函数
String s = new String(data, 0, length);
//输出
System.out.println("接收到来自"+sendIP+"的,端口号为"+sendPort+"的数据:"+ s);
}
/*//关闭
ds.close();*/
} }
/**
- @author Lynn
- @create 2020-12-16-11:21 */
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Scanner;
/**
发送端 */ public class UDPSend { public static void main(String[] args) throws Exception, UnknownHostException {
//建立连接
DatagramSocket ds=new DatagramSocket();
//循环发送
while (true){
//创建数据--灵活的数据
Scanner sc=new Scanner(System.in);
System.out.println("请输入数据:");
String s=sc.next();
//数据打包
byte[] data=s.getBytes();//将字符串转化为字节数组
int length= data.length;
InetAddress address=InetAddress.getByName("192.168.2.184");
int port=123;//必须与接收端的一致
DatagramPacket dp=new DatagramPacket(data,length,address,port);
//调用方法进行发送
ds.send(dp);
/*//关闭连接
ds.close();*/
}
练习
```java package Test01;
/**
- @author Lynn
- @create 2020-12-16-20:19 */
import java.io.IOException; import java.net.*; import java.util.Scanner;
/**
- 一、 项目需求:请用户完成一个UDP接收端作为模拟网络聊天室的操作。
- 1:创建UDP传输下的聊天室发送端UDPSend类
- 2: 创建UDP传输下的聊天室接收端 Room类
- 1.2. 操作步骤描述
- 建立项目目录:day14作业_Test2_1
- 创建UDPSend类,并包含main()方法;
- 在该main方法中
- a、建立UDP的Socket服务;
- b、将要发送的数据封装到数据包中;
- c、通过UDP的Socket服务将数据包发送出去;
- d、关闭Socket服务
- 创建Room类 使用UDP接收端实现网络聊天效果
- 该类中写main方法 步骤如下
- a、建立UDP的Socket服务,因为要接收数据,所以必须明确一个端口号;
- 添加while(ture)循环,不断的循环接收内容
- b、创建数据包,用于存储接收到的数据,方便用数据包对象的方法解析这些数据;
- c、使用UDP的Socket服务的receive方法接收数据并存储到数据包中;
d、通过数据包的方法解析这些数据; */ public class UDPSend { public static void main(String[] args) throws IOException { //建立UDP的Socket服务 DatagramSocket datagramSocket=new DatagramSocket();
//将数据存放到数据包 //循环发送 while (true){ Scanner sc=new Scanner(System.in); System.out.println(“请输入数据:”); String s=sc.next();
//打包数据 byte[] bytes=s.getBytes();//将字符串转换为字节数组 int length= bytes.length; InetAddress inetAddress=InetAddress.getByName(“192.168.2.184”); int port=8888; DatagramPacket dp=new DatagramPacket(bytes,length,inetAddress,port);
//发送 datagramSocket.send(dp);
///关闭服务 datagramSocket.close();/ }
} }
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException;
/**
- @author Lynn
@create 2020-12-16-20:38 */ public class Room { public static void main(String[] args) throws IOException {
//建立连接
DatagramSocket ds=new DatagramSocket(8888);
//不断循环接收数据
while (true){
//创建数据包接收数据
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes, bytes.length);
//接收数据包
ds.receive(dp);
//解析数据
InetAddress sendAddress=dp.getAddress();
String sendIP= sendAddress.getHostAddress();
int port=dp.getPort();
//存入
byte[] data=dp.getData();
int length= dp.getLength();
//将字节数组转换为字符串
String s=new String(data,0,length);
System.out.println("接收到来自"+sendIP+"的,端口号为:"+port+"的数据:"+s);
}
网络模型
网络模型是计算机网络通讯规范,一般符合以下规则:
OSI(Open System Interconnection开放系统互连)参考模型;
TCP/IP参考模型。TCP协议
案例1
```java package com.igeek_04;
/**
- @author Lynn
- @create 2020-12-16-14:23 */
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
/**
当前案例演示客户端发送信息,服务器端接收信息 */ public class Server { public static void main(String[] args) throws Exception {
//建立服务器端
ServerSocket serverSocket=new ServerSocket(8888);
//当前是服务器端,所以先获取IO流的同时需要等待客户端发送数据过来
Socket socket= serverSocket.accept();
//建立连接之后,通过Socket中的IO流进行数据传输
InputStream inputStream = socket.getInputStream();
//读取的是一个字节
int read = inputStream.read();
System.out.println((char)read);
//关闭--两个都要关闭
socket.close();
serverSocket.close();
} }
/**
- @author Lynn
- @create 2020-12-16-14:29 */
import java.io.IOException; import java.io.OutputStream; import java.net.Socket;
/**
- 客户端 *1.建立客户端
- 2.连接后,通过socket中的流进行传输
3.关闭 */ public class Client { public static void main(String[] args) throws Exception {
//建立客户端
Socket socket=new Socket("127.0.0.1",8888);
//建立连接后开始传输
OutputStream outputStream=socket.getOutputStream();
//输出数据
outputStream.write(97);
//关闭
outputStream.close();
案例2—演示跟同桌的初步信息传输
```java package com.igeek_05;
/**
- @author Lynn
- @create 2020-12-16-14:23 */
import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner;
/**
当前案例演示客户端发送信息,服务器端接收信息 */ public class Server { public static void main(String[] args) throws Exception {
//建立服务器端
ServerSocket serverSocket=new ServerSocket(8888);
//当前是服务器端,所以先获取IO流的同时需要等待客户端发送数据过来
Socket socket= serverSocket.accept();
//建立连接之后,通过Socket中的IO流进行数据传输
InputStream inputStream = socket.getInputStream();
//反复读取客户端发送的数据
int read=-1;
while ((read=inputStream.read())!=-1){
System.out.print((char)read);
}
//接收客户端数据后要返回一个o给客户端
while (true){
OutputStream outputStream=socket.getOutputStream();
Scanner sc=new Scanner(System.in);
System.out.println("请输入数据:");
String content=sc.next();
outputStream.write(content.getBytes());//将字符串转化为字节传输
}
/*//关闭--两个都要关闭
socket.close();
serverSocket.close();*/
}
}
```java
package com.igeek_05;
/**
* @author Lynn
* @create 2020-12-16-14:29
*/
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
/**
* 客户端
*1.建立客户端
* 2.连接后,通过socket中的流进行传输
* 3.关闭
*
* 改进:
* 客户端发送一个字符串:I Love Java信息,接收服务器端返回的一个字母o的响应
*
* void shutdownoutput():禁止输出流,告知对方
*/
public class Client {
public static void main(String[] args) throws Exception {
//建立客户端
Socket socket=new Socket("192.168.2.181",8888);
//建立连接后开始传输
OutputStream outputStream=socket.getOutputStream();
//输出数据
while (true){
Scanner sc=new Scanner(System.in);
System.out.println("请输入数据:");
String content=sc.next();
outputStream.write(content.getBytes());//将字符串转换为字节数组
//告诉服务器,不需要发送数据了
socket.shutdownOutput();
//获取服务器端的响应
InputStream inputStream= socket.getInputStream();
byte[] bytes=new byte[1024];
int len=-1;
while ((len= inputStream.read(bytes))!=-1){
String s=new String(bytes,0,len);
System.out.print(s);
}
/*//关闭
outputStream.close();*/
}
}
}
练习1
package Test02;
/**
* @author Lynn
* @create 2020-12-16-20:48
*/
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 一、 需求说明:使用TCP编写一个网络程序,设置服务器程序监听端口为8002,当于客户端建立后,向客户端发送”hello world”,客户端将信息输出
* 2.2. 操作步骤描述
* 1. 建立项目:day14作业_Test2_2
* 2. 创建TCPServer类,包含main()方法
* 使用ServerSocket创建服务器对象,监听8002端口,调用accept()方法等待客户端连接,当于客户端连接上之后,获取输出流对象,输出”hello world”
* 3. 创建TCPClient类,包含main()方法
* 使用Socket创建客户端对象,指定服务器IP和端口号,与服务器端建立连接后,获取输入流对象,读取数据,并打印.
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
//创建服务器对象,建立连接
ServerSocket serverSocket=new ServerSocket(8002);
//调用accept方法
Socket socket= serverSocket.accept();
//获取socket的io流
InputStream in= socket.getInputStream();
//读取数据
byte[] bytes=new byte[1024];
int len=-1;
while ((len=in.read(bytes))!=-1){
String s=new String(bytes,0,len);
System.out.println(s);
}
// in.close();
socket.close();
serverSocket.close();
}
}
package Test02;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* @author Lynn
* @create 2020-12-16-20:49
*/
public class TCPClient {
public static void main(String[] args) throws IOException {
//建立连接
Socket socket=new Socket("192.168.2.184",8002);
//获取流对象
OutputStream out= socket.getOutputStream();
//输入数据
String s="hello world";
byte[] bytes=s.getBytes();
out.write(bytes);
out.close();
socket.close();
}
}
案例3—文件上传
package com.igeek_06;
/**
* @author Lynn
* @create 2020-12-16-15:13
*/
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 文件上传,服务器端接收到客户端文件中的数据,向服务器端的另一个文件中写出
* 接收到文件内容,写到某个文件中
*
* 这里的数据是文件中的内容
*/
public class Server {
public static void main(String[] args) throws Exception {
//建立服务器端
ServerSocket serverSocket=new ServerSocket(8888);
//获取流
Socket socket = serverSocket.accept();
//建立连接以后获取socket的流
InputStream inputStream=socket.getInputStream();
//获取到上传文件的内容,要有一个文件
FileOutputStream fos=new FileOutputStream("面向对象堂测答案-copy.docx");
//反复使用一个字节读取
int len=-1;
while ((len= inputStream.read())!=-1){
//一次读取一个字节,最终这个文件接受了所有的上传数据
fos.write(len);
}
//关闭IO流
fos.close();
//给客户端返回一个响应
OutputStream out= socket.getOutputStream();
String content="o";
out.write(content.getBytes());
//关闭socket
socket.close();
serverSocket.close();
}
}
package com.igeek_06;
/**
* @author Lynn
* @create 2020-12-16-15:13
*/
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* 上传文件
* 读取文件内容,发送给服务器端
*/
public class Client {
public static void main(String[] args) throws Exception {
//建立客户端
Socket socket=new Socket("localhost",8888);
//建立连接后,获取socket的流
OutputStream out= socket.getOutputStream();
//获取文件对象
FileInputStream fis=new FileInputStream("面向对象堂测答案.docx");
//读取文件内容
int len=-1;
while ((len= fis.read())!=-1){
//输出数据给服务器
out.write(len);
}
//关闭流
fis.close();
//告知服务器,不再发送数据
socket.shutdownOutput();
//获取输入流,接收服务器端的响应
InputStream in= socket.getInputStream();
int read= in.read();
System.out.println((char)read);
socket.close();
}
}
练习2
/**
* @author Lynn
* @create 2020-12-16-21:08
*/
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 一、 需求说明:我们来做一个“文件上传案例”,有以下要求:
* 将项目中的一个图片,通过客户端上传至服务器
* 1.2. 操作步骤描述
* 1,创建服务器,等待客户端连接
* 2,创建客户端Socket,连接服务器
* 3,获取Socket流中的输出流,功能:用来把数据写到服务器
* 4,创建字节输入流,功能:用来读取数据源(图片)的字节
* 5,把图片数据写到Socket的输出流中(把数据传给服务器)
* 6,客户端发送数据完毕,结束Socket输出流的写入操作,告知服务器端
* 7,获取Socket的输入流
* 8,创建目的地的字节输出流
* 9,把Socket输入流中的数据,写入目的地的字节输出流中
* 10,获取Socket的输出流, 作用:写反馈信息给客户端
* 11,写反馈信息给客户端
* 12,获取Socket的输入流 作用: 读反馈信息
* 13,读反馈信息
*/
public class Server {
public static void main(String[] args) throws IOException {
//创建服务器,建立连接
ServerSocket serverSocket=new ServerSocket(8888);
//调用socket的接收方法
Socket socket=serverSocket.accept();
//接收socket的IO流
InputStream inputStream= socket.getInputStream();
//创建字节输出流
FileOutputStream fos=new FileOutputStream("jackson2-1.jpg");
//读取流中的内容
int len=-1;
while ((len= inputStream.read())!=-1){
fos.write(len);
}
fos.close();
//服务端接收到数据后给客户端一个响应
OutputStream out= socket.getOutputStream();
String s="over";
out.write(s.getBytes());
serverSocket.close();
socket.close();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* @author Lynn
* @create 2020-12-16-21:08
*/
public class Socker {
public static void main(String[] args) throws IOException {
//创建连接
Socket socket=new Socket("127.0.0.1",8888);
//获取流
OutputStream outputStream= socket.getOutputStream();
//读取文件内容
FileInputStream fis=new FileInputStream("jackson2.jpg");
int len=-1;
while ((len= fis.read())!=-1){
outputStream.write(len);
}
fis.close();
//告知服务器不再发送数据了
socket.shutdownOutput();
//客户端接收服务端的响应
InputStream inputStream= socket.getInputStream();
int length=-1;
while ((length= inputStream.read())!=-1){
System.out.print((char)length);
}
socket.close();
}
}