一、网络基础
一、TCP/IP协议
网络通信协议是计算机问进行通信所遵守的各种规则的集合。Internet的主要协议有:网络层的IP协议;传输层的TCP和UDP协议写;TCP协议是面向连接的,而UDP是面向不连接的,UDP传输速度更快,而TCP协议更安全;应用层的FTP、HTTP SMTP等协议。其中传输控制协议(Transpon Control Protocol, TCP)和网际互联协议(IntermetPoodIP是nemet的主要协议。它们定义了计算机与外设进行通信所使用的规则。
二、IP地址、域名和通信端口
- IP地址用于唯一标识一个网络接口。IPv4采用32位地址,已经用完;IPv6 采用128位地址。
-
域名表示一台网络中的电脑,由于IP地址不便于记忆,通常使用域名来访问特定的服务,域名解析服务器DNS负责将域名翻译成对应的IP地址,客户端再根据IP地址访问服务器:
- 通信端口唯一标识电脑上的一个进程(运行的程序)。端口号不是物理实体而是一个标记计算机逻相通有信道的正整数。端口号是用一个16位的-进制数来表示的,如果用十进制数来数来表示,,其范围为0~-65 535,其中,0~ 1023被系统保留。IP地址和端口号组成了所谓的TCP, UDP协议使用端口号将数的程序之间双向通信链路的最后终结点,是TCP和UDP的基础。Socket. Socker 是网络上运行的程序之间双向通信的链路的最终结点,是TCP和UDP的基础。
三、URL
URL是统一资源定位器Uniform Resource Locator
URL的基本结构由五部分组成,格式如下:
传输协议: //主机名:端口号//文件名#引用
- 传输协议 :TCP/IP协议
- 主机名: 指资源所在的计算机。可以是IP地址,也可以是计算机的名称或域
- 端口号:一个计算机中可能有多种服务,如Web服务,FTP服务或自己建立的服务>等。为了区分这些服务,就需要使用端口号,每一种服务用 一个端口号。
- 文件名:文件名包括该文件的完整路径。在HTTP协议中,有一个默认的文件名是index. html,因此,下列两个地址是等价的。
http://java.sun.com
http://java.sun.com/index.html- 引用:引用就是资源内部的某个参考点。例如:http://java.sun.con/index.html#chapter1
四、Socket通信模式
Socket通常称为套接字,用于应用程序之间建立远程连接,Socket内部通过TCP/IP协议进行数据传输,可以简单的理解为对IP地址和端口号的描述。Socket编程需要实现服务器端和客户端,因为这两个设备通讯时,需要知道对方的IP和端口号。通常服务器端有个固定的端口号,客户端直接通过服务器的IP地址和端口号进行访问服务器端,同时告知客户端的端口号,于是他们之间就可以通过socket进行通信。
二、Socket编程
(1)客户端和服务器端实现通信
模拟客户端:首先创建一个用于模拟客户端socket,指明和哪个服务器通信和通信的端口,这里的IP地址是10.129.25.52,通信端口可以随便来一个8989,然后创建一个BuBufferedReader对象接收服务器发送的数据,然后再读取数据;给服务器发送数据,创建一个输出流PrintStream,输出数据。
模拟服务器端:先创建一个模拟服务器serverSocket,然后就要获得是哪个客户端连接到这个服务器,获取这个客户端的socket,其他的传输数据和客户端的传输过程一样。
//模拟客户端
class Client{
public static void main(String[] args) throws IOException {
//1,创建用于通信的socket
// 指明和谁通信:IP地址 端口号
Socket socket = new Socket("10.129.25.52",8989);
//接受服务器发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取服务器端发送的数据
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
//向服务器端发送数据
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("你好啊");
socket.shutdownOutput();
}
}
//模拟服务器端
class Server{
public static void main(String[] args) throws IOException {
//1,创建服务器端的serverSocket
ServerSocket serverSocket = new ServerSocket(8989);
//2,获取连接的客户端的socket
Socket clientSocket = serverSocket.accept();
//3,向客户端发送数据
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("登陆成功");
//告诉客户端输出完毕
clientSocket.shutdownOutput();
//4,接收客户端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
}
}
(2)从终端输入数据,传送给客户端
这个和之前的区别就是,要先从终端读取数据,然后再传递给客户端
class MyClient{
public static void main(String[] args) {
//连接服务器端的socket
Socket socket = null;
try {
socket = new Socket("10.129.36.120",8888);
//接受服务器端数据
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(8888)) {
//监听客户端 获取哪个客户端访问
Socket clientsocket = ss.accept();
//从终端接受数据
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
PrintStream ps = new PrintStream(clientsocket.getOutputStream());
String line = null;
while((line = keyin.readLine())!= null){
//发送给客户端
ps.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)客户端向服务器端上传一张图片
注:传输图片,视频,音频要用字节流
class Client{
public static void main(String[] args) throws IOException {
//连接服务器 获取socket
Socket socket = new Socket("127.0.0.1",8080);
//创建服务器端对应的输入流 用于接收服务器端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服务器端发送文件(图片)
//1.将文件写入到内存里
String path = "/Users/pengxiaodong/Desktop/1.png";
FileInputStream fis = new FileInputStream(path);
//2.创建字节流 outputStream
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 {
//创建服务器端的ServerSoket
ServerSocket ss = new ServerSocket(8080);
//监听客户端连接
//当有客户端来连接这个服务器 就可以得到对应的socket
//当没有客户端来连接 服务器一直在这里等待
Socket socket = ss.accept();
//创建客户端对应的输出流 用于向这个客户端发送数据
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("连接成功 可以发数据了!");
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String path = "/Users/pengxiaodong/Desktop/day1/java/src/main/java/day12/media/2.png";
FileOutputStream fos = new FileOutputStream(path);
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
fos.write(buf,0,len);
}
}
}
(4)点对点聊天
- 客户端:
主线程:接受终端的输入,将终端的输入发送给服务器
子线程:接收服务器发过来的数据 - 服务器端:
主线程:接收终端输入 将终端的输入发送给客户端
子线程:接收客户端发过来的数据
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.25.52",8989);
//用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入 发送给服务器端
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//创建一个发送给服务器的对象
PrintStream printStream = new PrintStream(socket.getOutputStream());
String line = null;
while((line = keyin.readLine()) != null){
printStream.println(line);
}
}
}
/**
* 创建一个客户端子线程
*/
class ClientThread implements Runnable{
private Socket socket;
//构造方法 告诉子线程在哪里读数据
public ClientThread(Socket socket){
this.socket = socket;
}
//获取服务器端的输入流对象
BufferedReader bufferedReader = null;
@Override
public void run() {
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line = null;
while((line = bufferedReader.readLine()) != null){
System.out.println("服务器:"+line);
}
} catch (IOException e) {
System.out.println("网络异常,请重新登陆");
System.exit(-1);
}finally { //出现异常,所有的资源都应该关闭 先关小的
try {
if(bufferedReader != null) {
bufferedReader.close();
}
if(socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Server{
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8989);
//获取客户端的socket
Socket clientSocket = serverSocket.accept();
//创建子线程
new ServerThread(clientSocket).start();
//终端的输入流对象
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流
PrintStream printStream = new PrintStream(clientSocket.getOutputStream());
//读取终端的输入 将输入的内容输出给客户端
String line = null;
while((line = keyin.readLine()) != null){
printStream.println(line);
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的数据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
BufferedReader bufferedReader = null;
@Override
public void run() {
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line = bufferedReader.readLine()) != null){
System.out.println("客户端"+line);
}
} catch (IOException e) {
System.out.println("网络异常,请重新登陆");
System.exit(-1);
}finally {
try {
if(bufferedReader != null) {
bufferedReader.close();
}
if(socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
super.run();
}
}
(6)实现群聊。
class Server{
//保存连接服务器的客户端
public static ArrayList sockets = new ArrayList();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8384);
//不停的等待客户端来连接
while(true){
Socket socket = serverSocket.accept();
//当有客户端连接过来 就保存
sockets.add(socket);
//开启一个线程处理每个客户端的输入
new ServerThread(socket).start();
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的数据
* 群发消息
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
BufferedReader bufferedReader = null;
@Override
public void run() {
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line = bufferedReader.readLine()) != null){
//群发消息
//遍历数组
for(Socket socket1:Server.sockets){
//向每个对应的客户端发送消息
PrintStream printStream = new PrintStream(socket1.getOutputStream());
printStream.println(line);
}
}
} catch (IOException e) {
System.out.println("网络异常,请重新登陆");
System.exit(-1);
}finally {
try {
if(bufferedReader != null) {
bufferedReader.close();
}
if(socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
super.run();
}
}
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.25.52",8384);
//用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入 发送给服务器端
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//创建一个发送给服务器的对象
PrintStream printStream = new PrintStream(socket.getOutputStream());
String line = null;
while((line = keyin.readLine()) != null){
printStream.println(line);
}
}
}
class ClientThread implements Runnable{
private Socket socket;
//构造方法 告诉子线程在哪里读数据
public ClientThread(Socket socket){
this.socket = socket;
}
//获取服务器端的输入流对象
BufferedReader bufferedReader = null;
@Override
public void run() {
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line = null;
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常,请重新登陆");
System.exit(-1);
}finally { //出现异常,所有的资源都应该关闭 先关小的
try {
if(bufferedReader != null) {
bufferedReader.close();
}
if(socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}