1.基本网络概念
网络
--网络是相互发送和接受数据的计算机和其他设备的集合;
--每一个设备就是一个网络节点(node);
--每一个计算机是一个主机(host)
--每个网络节点有地址;
--以太网分配物理地址;
--Internet服务器分配Internet地址;
--地址可以有标识名字,但是不与地址锁定;
IP、TCP和UDP
IP地址网络中计算机的唯一标识
--P地址是用一个点来分成四段的,在计算机内部IP地址是用四个字节来表示的,一个字节代表一段,每一个字节代表的数最大只能到达255。
--IPv4地址,4字节地址,例如192.168.6.190
--包的首部保护目的地址和源地址
--IPv4地址已经用完,目前在向IPv6地址过渡
--IPv6地址,16字节地址,例如FEDC:7654:3210:FEDC:BA98:7654:3210
域名(DNS)
--用于记忆主机名,并在使用时转换为ip地址
--IP地址会随着时间变换
--127.0.0.1表示本地回送地址
--IPv6的本地回送地址为::1
端口正在运行的程序的标识。
--每台计算机有65535个端口
--1到1023保留给已知服务
客户/服务器模型
--服务端发送数据,客户端接收数据
--对等端通过服务器程序实现相互通信
TCP
建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低
--面向连接
--安全可靠
--效率稍低
--通过三次握手确保连接的建立
--举例:下载,打电话,QQ聊天(你在线吗,在线,就回应下,就开始聊天了)
UDP
将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快
--面向无连接
--不可靠
--速度快
--将数据封包传输,数据包最大64k
--举例:聊天留言,在线视频,视频会议,发短信,邮局包裹
网络通信三要素
IP地址:网络中设备的标识,不易记忆,可用主机名
端口号:用于标识进程的逻辑地址,不同进程的标识
传输协议(通讯的规则):常见协议:TCP,UDP
URL
URI=URL+URN
URI:Uniform Resource Identifier ,统一资源标志符。
URL:Uniform Resource Locator,统一资源定位符。
URN:Uniform Resource Name,统一资源命名。
TCP编程
--TCP是可靠的连接,TCP就像打电话,需要先打通对方电话,等待对方有回应后才会跟对方继续说话,也就是一定要确认可以发信息以后才会把信息发出去。TCP上传任何东西都是可靠的,只要两台机器上建立起了连接,在本机上发送的数据就一定能传到对方的机器上。
实例1:
服务器端
//模拟服务器端
class Service {
public static void main(String[] args) throws IOException {
//创建服务器端 表明自己端口号8989
ServerSocket ss = new ServerSocket(8989);
//一旦有客户端来链接 就获取客户端的socket
Socket clientSocket = ss.accept();
//向客户端发送数据
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
//bw.write("登陆成功");
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("登陆成功");
//输出完毕 关掉输出流
clientSocket.shutdownOutput();
//-----接收客户端发送的数据---//
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while ((line = br.readLine() )!= null){
System.out.println(line);
}
}
}
客户端
//模拟客户端
class Client{
public static void main(String[] args) throws IOException {
//1.创建用于通信的Scoket
// 指明和谁通信:ip地址 端口号
Socket socket = new Socket("127.0.0.1",8989);
//接收服务器的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//向服务器发送数据
//socket.getOutputStream();
//读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//---客户端向服务器发送数据---//
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好啊!");
socket.shutdownOutput();
}
}
执行结果:
$FERE4RRV4E4}{SURXG)7ZX.png
![(UOO0B%@KH7%I1W3{4]09`Q.png](https://img.haomeiwen.com/i18945157/f927ea0e7a64e06d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在上面结果可以看出,服务器与客户端都进行了数据的交换
实例2
/**
* 手动输入内容发送
* 客户<--> 1.文本 2.图片 3.视频 4.音频 <-->服务器端
*/
/**----模拟客户端----*/
class MyClient {
public static void main(String[] args) {
//链接服务器端的socket
Socket socket =null;
try {
socket = new Socket("127.0.0.1",8989);
//接收服务端发送的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//从键盘输入的数据 发送给服务器
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("链接出错");
}finally {
//关闭链接
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**----模拟服务器端----*/
class MyServer {
public static void main(String[] args) {
//创建ServerSocket
try(ServerSocket ss = new ServerSocket(8989)){//在括号里面会自动释放
//监听客户端链接
Socket socket = ss.accept();
//从终端接收数据
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//创建向客户端输出的输出流
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
//调用刚刚创建的客户端输出流 发送信息给客户端
ps.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
上面程序执行的结果是:服务端可以从键盘输入数据,在发送给客户端
实例3
package day13media;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 客户端向服务器端上传图片
*/
public class MyClass {
}
/**----模拟客户端----*/
class Client{
public static void main(String[] args) throws IOException {
//链接服务器端 获取socket
Socket socket = new Socket("127.0.0.1",8989);
//创建服务器端对应的输入流 用于接收服务器端发送过来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服务器端发送图片
//1.将文件写入到内存
String path ="C://Users//18168//Desktop//yz.jpg";
FileInputStream fis = new FileInputStream(path);
//创建一个输出流
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] buf = new byte[1024];
int len = -1;
while((len = fis.read(buf)) != -1){
//开始向输出流中写入数据
bos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
/**----模拟服务器端----*/
class Server{
public static void main(String[] args) throws IOException {
//创建服务器端的serverSocket
ServerSocket ss = new ServerSocket(8989);
//监听客户端的链接,一但有客户端来链接就能得到socket,如果没有客户端来链接,服务器就会一直等待
Socket socket = ss.accept();
//创建客户端对应的输出流 用于向客户端发送数据
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("链接成功,可以发送数据!");
//接收客户端传递过来的图片 就是接上面客户端的输出流
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//文件对应的输出流 也就是将获取的数据保存
String path ="C://Users//18168//AndroidStudioProjects//java3//Java3//src//main//java//day13media/yz1.jpg";
//创建写入的对象 并且指定要写入的路径
FileOutputStream fos = new FileOutputStream(path);
byte[] buf = new byte[1024];
int len = -1;
while ((len = bis.read(buf)) != -1){
//开始写数据
fos.write(buf,0,len);
}
}
}
执行结果:在对应的目录下有一张名字为:yz1.ipg的图片
实例4
--创建群聊,用一台电脑当服务器,其他电脑通过服务器的ip链接服务器,就可以实现多人聊天,这个实例涉及到多线程
package group;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
/**
* 群聊天
* 1.在服务器端维护一个数组【socket】
* 客户端和服务器端都可以随意的发送内容
* 2.客户端:
* 主线程:接收终端输入 将终端输入的数据发送给服务器
* 子线程:接收来自服务器端发送的数据
* 3.服务器端:
* 主线程:接收终端输入 将终端输入的数据发送给客户端
* 子线程:接收来自客户端发送的数据
*/
/**----创建服务器端主线程----*/
class Server{
//保存每一个链接过来的对象
public static ArrayList<Socket> sockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8989);
//不停的等待客户端的链接
while (true) {
Socket socket = ss.accept();
//当有客户端链接过来就保存
sockets.add(socket);
//开启一个线程处理每个客户端的输入
new ServerThread(socket).start();
}
}
}
/**----创建服务器端子线程----*/
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String lint = null;
while ((lint = br.readLine()) != null) {
//群发消息
//遍历Server维护的数组
for (Socket s:Server.sockets) {
//向socket对应的客户发送消息
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(lint);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
//为了不浪费资源,要将流关闭
br.close();
}
if (socket != null) {
//为了不浪费资源,要将流关闭
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**----模拟客户端----*/
class Client{
public static void main(String[] args) throws IOException {
//这里指明服务器的ip地址和端口号
Socket socket = new Socket("10.129.28.253",6666);
//用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入并且给服务器发送
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
/**----创建客户端子线程----*/
class ClientThread implements Runnable{
private Socket socket;
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
//为了使finally能使用到这个,将其的作用域扩大
BufferedReader br = null;
try {
//获取服务器输入流对象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (br != null){
//为了不浪费资源,要将流关闭
br.close();
}
if (socket != null){
//为了不浪费资源,要将流关闭
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这个例子还有很多需要完善的地方,后期再慢慢更新!
感悟
学到这里慢慢的感觉java的乐趣来了,不再是那些枯燥的类与继承,而是一些比较好玩的编程,虽然看似简单,可是后面这些再也不是单一的知识点,而是要将前面学习的很多东西联系起来!
网友评论