java网络编程
1.1概述
地球村:你在西安,你一个美国的朋友!你们之间是怎么交流的?
1.11举个送信件的栗子
信件对方的地址,对方的信息定位到特定个体。自己的地址自己的信息
有了以上这些要素后不考虑外部环境,这封信理论上就能发送到对方的手里了。
如果考虑外部环境呢?
1.12 计算机网络的定义
将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机网络系统。
1.13网络编程的目的
传播交流信息,数据交换,通信(都是同一个意思)
1.14 想要达到这个效果需要什么?
1.如何准确的定位网络上的一台主机
地址:端口号 栗子如下
192.168.16.124:8080
定位到这个计算机上的某个程序
2.找到了这个主机上的某一程序,如何传输数据呢?
网络编程: TCP/IP协议 C/S架构
1.2网络通信的要素
如何实现网络的通信?
通信双方地址:
iP
端口号
192.168.16.124:5900
规则:网络通信的协议
TCP/IP
小结:
1.网络编程中有两个主要的问题
如何准确的定位到网络上的一台或多台主机
找到主机之后如何进行通信
2.网络编程中的要素
IP和端口号
网络通信协议 UDP,TCP
3.万物皆对象
1.3、IP地址
1.31 java中的关于ip地址的类
InetAddress
1.32一个关键的地址:
本机地址:127.0.0.1和localhost
查询ip地址实践代码
package com.kuang.lession01;
import java.net.InetAddress;
import java.net.UnknownHostException;
//记得类名一致,不然会报错的
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1=InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress3=InetAddress.getByName("localhost");
System.out.println(inetAddress3);
InetAddress inetAddress4=InetAddress.getLocalHost();
System.out.println(inetAddress4);
//查询网络ip地址
InetAddress inetAddress2=InetAddress.getByName("www.baidu.com");//输入的是一个域名他会返回该域名对应的ip地址
System.out.println(inetAddress2);
//常用方法
System.out.println(inetAddress2.getAddress());//大一地址
System.out.println(inetAddress2.getCanonicalHostName());//规范的名字
System.out.println(inetAddress2.getHostAddress());//ip
System.out.println(inetAddress2.getHostName());//域名或者自己电脑的名字
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1.33 ip地址分类
Ipv4/ipv6
IPV4 127.0.0.1,4字节组成。0~255,42亿,30亿在北美,亚洲4亿
IPV6:128位8个无符号整数!比如2001:obb2:aaaa:0015:0000:0000:1aaa:1312
公网(互联网)–私网(局域网)
ABCD类地址
192.168.xx.xx专门给组织内部使用的
小知识:域名是为了方便记忆,每个域名都对应一个IP地址,计算机识别域名映射的IP地址后在去执行操作的。
1.4端口
1.41 端口表示计算机上的一个程序的进程
不同的进程有不同的端口号!用来区分软件!
规定端口号区间:0~65535
其中TCP/UDP不同协议端口号可以相同:TCP/UDP:65535*2 tcp:80 udp:80这是可以的
可是单个协议下,端口号不能冲突
1.42 端口分类
公有端口 0~1024
HTTP:80
HTTPS:443
FTP:21
Telent:23
程序注册端口:1024 -49151,分配给用户或程序的
Tomcat:8080
MySQL:3306
Oracle:1521
动态、私有:49152~65535
1.43 查询端口实践
netstat -ano //查看所有的端口
netstat -ano|findstr “5353”查看指定端口端口
注:要确定所有端口里面有5353,不然可能检索了个寂寞
tasklist|findstr "20568"查看指定端口的进程
注:要确定该端口有对应进程才行
确认方法如下
Ctrl+shift+ESC 打开任务管理器
小知识:通过修改hosts C:\Windows\System32\drivers\etc\hosts,可以直接修改127.0.0.1hostsname,的映射名字
网络地址小实践
稍微熟悉java中 InetSocketAddress类的用法
package com.kuang.lession01;
import java.net.InetSocketAddress;
public class TestInetSockeAddress {
public static void main(String[] args) {
// TODO Auto-generated method stub
InetSocketAddress socketAddress=new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress1=new InetSocketAddress("localhost",8080);
System.out.println(socketAddress);
System.out.println(socketAddress1);
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getPort());//端口
System.out.println(socketAddress.getHostName());//地址
}
}
1.5 通讯协议
协议:约定就好比我们现在说普通话写汉字,你能看懂,如果我划拉的是西班牙语,可能你就看不懂了,更不用说进行通讯了
网络通讯协议:速率,传输码率,代码结构,传输控制…
两个重要协议:
TCP:用户传输协议
UDP:用户数据报协议
TCP UDP对比
TCP
- 目的连接,且稳定
- 连接的三次握手
- 断开的四次挥手
连接最少需要三次,才能保证稳定连接!断开最少四次才能稳定断开!
连接的三次握手:A:请求连接、B同意连接、AB连接
断开的四次挥手:A:请求断开 B:同意断开 B:断开,A:断开
UDP
- 不建立连接,也不稳定
- 客户端,服务端:没有明确的界限
- 不管有没有准备好,都可以发给你
- DDOS 饱和攻击
TCP程序实践
以下是一次根据java的网络编程原理实现的远程聊天程序。
远程聊天程序
客户端
- 连接服务器Socket
- 发送消息
package lesson02;
//客户端
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc =new Scanner(System.in);
System.out.println("请输入你要发送给服务端的文字:");
while(true)
{
Socket socket=null; //扩大Socket和OutpytStream 的作用域方便最后解决异常抛出情况
OutputStream os=null;
String str =sc.next();
try {//核心
//1. 要知道服务器的地址,端口号
InetAddress serverIP=InetAddress.getByName("127.0.0.1");
int port = 9921;
//2.创建一个socket连接
socket=new Socket(serverIP, port);
//3.发送消息IO流
os=socket.getOutputStream();
os.write(str.getBytes());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
/*
* 关闭异常以下是大公司解决异常的基本模板
*/
if(os!=null) {
try {
os.close();
} catch (IOException e2) {
// TODO: handle exception
}
}
if(socket!=null)
{
try {
socket.close();
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
}
}
服务器
- 建立服务的端口ServerSocket
- 等待用户的链接 accept
- 接受用户的消息
package lesson02;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket=null;
Socket socket=null;
InputStream is =null;
ByteArrayOutputStream baos=null;
try {
//1.新建一个地址
serverSocket=new ServerSocket(9921);
while(true)
{
//2.等待客户端连接过来
socket=serverSocket.accept();
//3.读取客户端的消息
is =socket.getInputStream();
//把输入流通过一个管道接一下
//管道流
baos=new ByteArrayOutputStream();//输出到控制台
byte[]buffer=new byte[1024];
int len;
while((len=is.read(buffer))!=-1) {//当没有结束时候将内容都写入baos
baos.write(buffer,0,len);
}
System.out.println(baos.toString()); //输出
}
} catch (IOException e) {
// TODO Auto-generated catch block
//关闭
e.printStackTrace();
}finally {
//关闭资源
if(baos!=null) {
try {
baos.close();
} catch (IOException e2) {
// TODO: handle exception
}
}
if(is!=null)
{
try {
is.close();
} catch (IOException e2) {
// TODO: handle exception
}
}
if(socket!=null)
{
try {
socket.close();
} catch (IOException e2) {
// TODO: handle exception
}
}
if(serverSocket!=null)
{
try {
serverSocket.close();
} catch (IOException e2) {
// TODO: handle exception
}
}
}
}
}
注:1.eclipse如何开多个控制台运行?
可以看这个博客:
2.遇到bind:address already in use
怎么办?
解决方法:可以看这个博客
实现远程文件传输
客户端
package lesson03;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TcpClientDemo02 {
public static void main(String[] args) throws IOException {
//1.客户端使用本地的字节输入流,读取要上传的文件
FileInputStream fis = new FileInputStream("D:\\socket\\input\\2.txt");
//2.客户端使用网络字节输出流,把读取到的文件上传到服务器
Socket socket = new Socket("127.0.0.1",8687);
OutputStream os = socket.getOutputStream();
int len = 0;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes))!=-1) {
os.write(bytes, 0, len);
}
//解决:上传完文件,给服务器写一个结束标记 void shutdownOutput() 禁止此套接字的输出流
//对于TCP套接字,任何以前写入的数据都将被法师,并且后面的TCP的正常连接终止序列
socket.shutdownOutput(); //结束输出流
//6.客户端使用网络字节输入流,读取服务器回写的数据
InputStream is = socket.getInputStream();
while ((len = is.read(bytes))!=-1) {
System.out.println(new String(bytes,0,len));
}
fis.close();
socket.close();
}
}
服务端
package lesson03;
import java.io.File;
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 TcpServerDemo02 {
public static void main(String[] args) throws IOException {
//3.服务器使用网络字节输入流,读取客户端上传的文件
ServerSocket ss = new ServerSocket(8687);
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
//判断服务器文件夹中是否已经上传过
File file = new File("D:\\socket\\output");
if (!file.exists()) {
file.mkdir();
}
//4.服务器使用本地字节输出流,把读取到的文件,保存到服务器的硬盘上
FileOutputStream fos = new FileOutputStream(file+"\\2.txt");
int len = 0;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes))!= -1) {
fos.write(bytes,0,len);
}
//5.服务器使用网络字节输出流,给客户端回写一个“上传成功”
OutputStream os = socket.getOutputStream();
os.write("上传成功".getBytes());
fos.close();
socket.close();
ss.close();
}
}
UDP编程实例:
利用UDP实现远程聊天
UdpReceiveDemo.java
package UdpChat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpReceiveDemo {
public static void main(String[] args) throws Exception {
DatagramSocket socket=new DatagramSocket(6668);
while(true) {
//2、准备接受包裹
byte[] datas=new byte[1024];
DatagramPacket packet=new DatagramPacket(datas,0,datas.length);
socket.receive(packet);//阻塞式接受
//3、输出包裹并准备断开连接 bye
byte[] data=packet.getData();
String receiveData=new String(data,0,data.length);
System.out.println(receiveData);
if(receiveData.trim().equals("bye")) {//不加trim会由于发出来的包里面含有大量空格导致无法比较,需要删掉空格
break;
}
}
socket.close();
}
}
UdpSenderDem.java
package UdpChat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class UdpSenderDemo {
public static void main(String[] args) throws Exception {
DatagramSocket socket=new DatagramSocket(8888);
while(true) {
//2、准备数据
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
String data=reader.readLine();
byte[] datas=data.getBytes();
DatagramPacket packet=new DatagramPacket(datas, 0,datas.length,new InetSocketAddress("localhost",6668));
//3、发送数据
socket.send(packet);
if(data.equals("bye")) {
break;
}
}
socket.close();
}
}