Day23
一、网络编程
1、计算机网络:是不同地方借助网络来进行数据传输和交互的媒介
2、网络编程的三大要素:IP、端口号、协议
3、InetAddress(java提供获取IP的类)
- public static InetAddress getLocalHost():返回本地主机;
- public String getHostAddress():获取ip地址;
- public String getHostName():获取ip的主机名;
4、端口号:当软件开启后,系统默认生成一个最大长度为两个字节的十进制,也可以自己设置
常用软件的端口号:
- Tomcat:8080
- oracle:1521
- mysql:3306
- qq:4000
- 网易邮箱的端口号:137
二、协议(主要是传输层:TCP、UDP+xmpp协议==>即时通讯qq、微信)
1、UDP面向无连接的协议:传输的数据快,但是可能会丢数据,出现卡顿
2、TCP面向连接的协议:传输慢,不会丢失数据(创建连接需要三次握手)《QQ》
3、HTTP、HTTPS都是属于一次性的连接,也就是客户端与服务器交互完后,请求就会断开《HTTPS=HTTP+ssl证书,保证了数据传输的安全性,大部分网站都是使用这个协议》
三、面向TCP协议进行通信
1、Socket类提供建立连接套接字的方式,即两个机器间通信的端点
2、构造方法:public Socket(String host,int port):传递两个参数,一个ip地址,一个是端口号(如果是本机ip地址传递localhost)
3、常规的方法:
- public OutputStream getOutputStream()throws IOException:写数据的流对象;
- public InputStream getInputStream()throws IOException:读取数据的流对象;
- public void shutdownOutput()throws IOException:关闭对应端口的输出流(单方面);
- public void shutdownInput()throws IOException:关闭对应端口的输入流(单方面);
注意:
- 在客户端或服务端通过socket.shutdownOutput()都是单向关闭的,即关闭客户端的输出流并不会关闭服务端的输出流,所以是一种单方向的关闭流
- 通过socket.shutdownOutput()关闭输出流,但socket仍然是连接状态,连接并未关闭
- 如果直接关闭输入或输出流,即in.close()或out.close(),会直接关闭socket
- 服务器(ServerSocket实现服务器套接字)
package com.yxlim.day23;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 先启动服务端,再启动客户端
*/
public class TCPServer {
public static void main(String[] args) {
try {
//创建服务器端口
ServerSocket server = new ServerSocket(6666);
//阻塞式接收连接,连接成功返回socket对象
Socket socket = server.accept();
//获取连接传输的输入流
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String s = null;
while ((s = br.readLine()) != null) { //读取数据
System.out.println(s);
}
socket.shutdownInput();//(单方面)关闭服务器输入流
//回应
OutputStream os=socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("Hi");
bw.flush();
socket.shutdownOutput();//(单方面)关闭服务器输出流
bw.close();//关闭流
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 客户端
package com.yxlim.day23;
import java.io.*;
import java.net.Socket;
/**
* 先启动服务端,再启动客户端
*/
public class TCPClient {
public static void main(String[] args) {
try {
//建立客户端端口
Socket socket=new Socket("localhost",6666);
OutputStream os=socket.getOutputStream();
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));
bw.write("Hello");
bw.flush();
socket.shutdownOutput();
//接收回应
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String s=null;
while ((s=br.readLine())!=null){
System.out.println(s);
}
socket.shutdownInput();
br.close();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 多线程服务器(接收多个客户端的连接)
package com.yxlim.day23.ThreadServer;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 多线程服务器(客户端不变)
*/
public class TCPServer extends Thread{
private Socket socket;
//利用构造器传入端口
public TCPServer(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
//获取端口输入流
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String s = null;
while ((s = br.readLine()) != null) {
System.out.println(s); //打印传输的数据
}
socket.shutdownInput();//关闭端口输入流
//回应
OutputStream os=socket.getOutputStream();//获取端口的输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("Hi");//输出数据
bw.flush();
socket.shutdownOutput(); //关闭端口输出流
bw.close();
br.close();//关闭流,也会关闭连接
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
//建立服务器端口
ServerSocket server= new ServerSocket(7777);
while (true) { //当有客户端访问,利用线程建立一条连接
Socket socket=server.accept();
new TCPServer(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、使用socket实现文件的上传的功能(客户端上传文件、服务器下载到服务器的存储),客户端+服务器+IO流文件读取写入操作
四、面向UDP协议进行通信
1、传输类主要是DatagramSocket(表示建立用来发送和接收数据报的套接字)、DatagramPacket(表示将数据报打包传输)
2、DatagramSocket构造方法:
- public DatagramSocket(int port,InetAddress laddr):第一个数端口号,第二个参数是地址;
- public DatagramSocket(int port):参数是端口号
(1)常规方法:
- public void send(DatagramPacket p)throws IOException:发送数据包;
- public void receive(DatagramPacket p)throws IOException:接收数据包;
3、DatagramPacket构造方法:
- DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port);
- DatagramPacket(byte[] buf, int offset, int length, SocketAddress address);
(1)常规方法:
- public SocketAddress getSocketAddress():返回的就是SocketAddress;
- public byte[] getData():获取缓冲区的数据;
4、实现Runnable接口实现多线程UDP通信
package com.yxlim.day23.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 服务器
*/
public class Server implements Runnable{
private DatagramSocket server;//创建服务器套接字
private String name;//对话人姓名
public Server(int port,String name){
this.name=name;
try {
server=new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
byte[] container = new byte[1024 * 60];//创建容器
//包装容器
DatagramPacket dp = new DatagramPacket(container, 0, container.length);
server.receive(dp);//阻塞式接收数据包
byte[] datas = dp.getData();//将数据包转成字节数组
int len = dp.getLength();
String s=new String(datas, 0, len);//将字节数组转成字符串
System.out.println(name+":"+s);
if("再见".equals(s)){//退出(需要通信双方都退出才算退出)
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
server.close();//关闭服务器
}
}
package com.yxlim.day23.UDP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* 客户端
*/
public class Client implements Runnable{
private DatagramSocket client;//创建客户端套接字
private BufferedReader reader;//创建键盘输入
private String toIP;//服务器IP
private int toPort;//服务器端口
public Client(int port,String toIP,int toPort){
this.toIP=toIP;
this.toPort=toPort;
try {
client=new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
reader=new BufferedReader(new InputStreamReader(System.in));
}
@Override
public void run() {
while (true){
try {
String s=reader.readLine();//键盘输入字符串
byte[] datas=s.getBytes();
//打包成数据包
DatagramPacket packet=new DatagramPacket(datas,0,datas.length,
new InetSocketAddress(toIP,toPort));
client.send(packet);//发送数据包
if("再见".equals(s)){//退出(需要通信双方都退出才算退出)
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
client.close();//关闭客户端
}
}
public class TalkOne {
public static void main(String[] args) {
new Thread(new Server(5555,"xiao李")).start();//接收
new Thread(new Client(6666,"localhost",7777)).start();//发送
}
}
public class TalkTwo {
public static void main(String[] args) {
new Thread(new Client(8888,"localhost",5555)).start();//发送
new Thread(new Server(7777,"xiao范")).start();//接收
}
}
- 基于UDP比较繁琐,且没有获取流对象的方法,开发中多用第三方jar包