1. 网络相关概念
-
网络通信
1.概念:两台设备之间通过网络实现数据传输
2.网络通信;将数据通过网络从一台设备传输到另一台设备
3.java.net包下提供了一系列的类或借口哦,供程序员使用,完成网络通信 -
网络
1.概念:两台或多台设备通过一定物理设备连接起来构成了网络
2.根据网络的覆盖范围不同,对网络进行分类:
局域网:覆盖范围最小,仅仅覆盖一个教室或一个机房
城域网:覆盖范围较大,可以覆盖一个城市
广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网是广域网的代表 -
ip地址
1.概念:网络中每台计算机/主机的唯一标识
2.查看ip地址:ipconfig
3.ip地址的表示形式:ipv4 32位十进制 00.00.00.00
ipv6 128位十六进制 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
4.每一个十进制数的范围:0~255
5.ip地址的组成:网络地址+主机地址=163.196.10.1 (163.196.10就是网络地址 1是主机地址)
6.IPv6是Ipv4的升级,尚在推广普及中,现在用的最多的还是IPv4 -
ip地址的分类
1.按IP地址分类
IPv4分为A类、B类、C类、D类、E类
本机:127.0.0.1
2.公网(互联网) - 私网(局域网) -
域名
1.www.baidu.com
2.方便记忆
3.概念:将ip地址映射成域名 -
端口号
1.概念:用于标识计算机上某个特定的网络程序
2.表示形式:以整数形式,范围0~65535
3.0~1024已经被占用
4.常见的网络程序端口号:
tomcat:8080
mysql:3306
oracle:1521
sqlserver:1433 -
网络通信协议
http、ftp、smtp、TCP
OSI七层网络模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
TCP/IP四层概念模型:应用层、传输层、网络层、数据链表层
TCP/UTP是属于传输层的协议
1.网络编程有两个主要的问题:如何定位网络上的一台、多台主机?找到主机之后如何进行通信?
2.网络编程中的要素:IP和端口号、网络通信协议 -
Java中IP对应的类
InetAddress
2.TCP
2.1.客服端
- 主要任务
1.通过Socket连接服务器
2.发送数据
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class C {
public static void main(String[] args) throws IOException {
String ip = "127.0.0.1";
InetAddress serverIP = InetAddress.getByName(ip);
int port = 6080;
Socket socket = new Socket(serverIP,port);
OutputStream os = socket.getOutputStream();
os.write("你好,本地".getBytes());
os.close();
socket.close();
}
}
2.2 服务器
- 主要任务
1.建立服务器
2.等待客户端连接
3.接收数据
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class S {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
PrintStream ps = System.out;
{
try {
serverSocket = new ServerSocket(6080);
socket = serverSocket.accept();
is = socket.getInputStream();
int len;
byte[] bytes = new byte[1024];
while ((len=is.read(bytes))!=-1){
ps.write(bytes,0,len);
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
ps.close();
if (is!=null){
try {
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
服务器启动后,会等待客户端建立连接,以便接收数据,一般一台服务器服务于多个客户端,因此等待连接的命令是循环的。
2.3 TCP传输文件
将图片上传
- 服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class S {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
FileOutputStream fos = null;
{
try {
serverSocket = new ServerSocket(6080);
socket = serverSocket.accept();
is = socket.getInputStream();
fos = new FileOutputStream(new File("ok.jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
if (fos!=null){
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fos!=null){
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (is!=null){
try {
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
- 客户端
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class C {
public static void main(String[] args) throws IOException {
String ip = "127.0.0.1";
String filePath = "e:/licen.jpg";
InetAddress serverIP = InetAddress.getByName(ip);
int port = 6080;
FileInputStream fis = new FileInputStream(filePath);
Socket socket = new Socket(serverIP,port);
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len=fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
os.close();
socket.close();
fis.close();
}
}
我们在上传文件时,需要再客户端先将内存的文件读取到idea中(输入流),再上传数据到服务器(输出流),同样,服务器先接收数据(输入流),在输出保存数据到内存(输出流)。
3. UDP
不同于TCP,UDP不需要建立连接,就可以对接收端发送数据。
3.1 发送端
public class UdpC {
public static void main(String[] args) throws Exception {
//建立Socket
DatagramSocket socket = new DatagramSocket();
//建立信息
String mes = "Hello ah ,brother shu";
//地址信息
InetAddress localhost = InetAddress.getLocalHost();
int port = 6080;
//创建包,数据,数据的长度,发送地址
DatagramPacket packet = new DatagramPacket(mes.getBytes(),0,mes.getBytes().length,localhost,port);
//发送包
socket.send(packet);
//关闭流
socket.close();
}
}
我们即使没有与接收端建立连接,也可以发送数据,代码也能正常运行。
3.2 接收端
public class UdpS {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket socket = new DatagramSocket(6080);
//接收数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
//阻塞接收
socket.receive(packet);
//输出数据来源,输出数据
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//关闭流
socket.close();
}
}
在建立服务器后,可以接收到数据。
3.3 聊天建立
- 发送
public class UdpSender {
public static void main(String[] args) throws Exception {
//端口
DatagramSocket socket = new DatagramSocket(6688);
//接收输入
BufferedReader bufR = new BufferedReader(new InputStreamReader(System.in));
//建立包
while (true){
String sdata = bufR.readLine();
byte[] data = sdata.getBytes();
DatagramPacket packet = new DatagramPacket(data,0,data.length,new InetSocketAddress("localhost",6655));
//发送包
socket.send(packet);
//关闭流
if (sdata.equals("close"))
break;
}
bufR.close();
socket.close();
}
}
- 接收
public class UdpReceive {
public static void main(String[] args) throws Exception {
//端口
DatagramSocket socket = new DatagramSocket(6655);
//接收包
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
while (true){
//接收数据
socket.receive(packet);
byte[] data = packet.getData();
int len = data.length;
String rdata = new String(data,0,len);
System.out.println(rdata.trim());
//停止聊天
if (rdata.trim().equals("close")){
break;
}
}
socket.close();
}
}
注意
因为没有建立连接,并且刚刚开始运行时,没有接收到包输入,这里container数组的长度是1024,除了有效的输入,其他位置会默认为0,导致我们的包的数据长度也是1024,包括下面拿出包里的数据,转换成字符串时,字符串会在有效的数据后加上空,输出时我们要输出String.trim(),保证只输出有效字符,我在寻找更有效的解决办法,能解决一开始的字节数组会自动填充0的问题。
3.4 多线程实现互相聊天
- 接收工具类
public class Recive extends Thread{
DatagramSocket socket = null; //端口
int port;
public Recive(int port) throws SocketException {
this.port = port;
socket = new DatagramSocket(port);
}
@Override
public void run() {
while (true){
//接收包
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
//接收数据
try {
socket.receive(packet);
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] data = packet.getData();
int len = data.length;
String rdata = new String(data,0,len);
System.out.println(rdata.trim());
//停止聊天
if (rdata.trim().equals("close")){
break;
}
}
socket.close();
}
}
- 发送工具类
public class Send extends Thread{
DatagramSocket socket; //端口
//接收输入
BufferedReader bufR ;
String ip;
int port;
int toport;
public Send(String ip,int port,int toport) throws SocketException {
this.ip = ip;
this.port=port;
this.toport = toport;
socket = new DatagramSocket(port);
bufR = new BufferedReader(new InputStreamReader(System.in));
}
@Override
public void run() {
//建立包
while (true){
String sdata ;
try {
sdata = bufR.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] data = sdata.getBytes();
DatagramPacket packet = new DatagramPacket(data,0,data.length,new InetSocketAddress(ip,toport));
//发送包
try {
socket.send(packet);
} catch (IOException e) {
throw new RuntimeException(e);
}
//关闭流
if (sdata.equals("close"))
break;
}
try {
bufR.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
socket.close();
}
}
- 用户
public class chatUser {
public static void main(String[] args) throws Exception {
Send send = new Send("localhost",6685,6688);
Recive recive = new Recive(6655);
send.start();
recive.start();
}
}
public class chatUser2 {
public static void main(String[] args) throws Exception {
Send send = new Send("localhost",6658,6655);
Recive recive = new Recive(6688);
send.start();
recive.start();
}
}
- 对话效果