1 网络编程
1.1 网络编程概述
-
什么网络:分存在不同区域计算机使用专业通信线把连接起来,实现资源(数据,硬件)共享。
-
网络编程目的:通过通讯协议实现数据传输
-
如何通信
-
ip和端口
ip: Internet网络唯一标识.
端口:计算机中运行的一个进程
-
通讯协议的约定
TCP:传输控制协议
UDP:用户数据报协议
-
1.2 通讯要素
-
IP地址和端口
InetAddress类:此类表示Internet协议(IP)地址
端口号:0-65535 系统预留:0-1023 自定义端口:1024-65535
如:mysql端口:3306
@Test
public void test1() throws Exception {
InetAddress inet = InetAddress.getByName("www.baidu.com");
//InetAddress inet = InetAddress.getByName("182.61.200.6");
System.out.println(inet);
System.out.println(inet.getHostName());
System.out.println(inet.getHostAddress());
//本机 localhost 127.0.0.1 本地的回环地址(用于测试本机)
//ipconfig --查看当前机器的ip地址
//ping ip --检查网络是否畅通
inet= InetAddress.getByName("127.0.0.1");
System.out.println(inet.getHostName());
System.out.println(inet.getHostAddress());
//本机
InetAddress inet1 = InetAddress.getLocalHost();
System.out.println(inet1.getHostName());
System.out.println(inet1.getHostAddress());
}
-
通讯协议
TCP :传输控制协议 UPD:用户数据报 l> 必须建立连接,形成传输通道 将数据、源、目的封装成数据包,不必须建立连接 传输前,采用“三次握手”,是可靠的 数据包大小是64K Tcp通信位于两个进程 (客户端-服务端) 因无需连接,故不可靠 可以传输大量的数据 传完数据无需释放资源 效率高 传完需要释放己建立的连接 效率低 -
传递的socket套接字
ip地址和端口的组合
网络通信其实就是Socket间的通信,以流的方式进行传输
一般主动发起通信应用程序叫客户端,等待接受数据叫服务端‘
客户端:Socket
Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号。
getInputStream() 返回此套接字的输入流。
getOutputStream() 返回此套接字的输出流。
服务端:ServerSocket
ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
Socket=accept() 侦听要连接到此套接字并接受它。
getInputStream() 返回此套接字的输入流。
getOutputStream() 返回此套接字的输出流。
1.3 TCP网络协议通讯
public class TestTcp3 {
//客户端
@Test
public void client() throws IOException {
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),8888);
//发送
OutputStream os = socket.getOutputStream();
//本地读取文件
FileInputStream fis = new FileInputStream(new File("a.txt"));
byte[] bs = new byte[1024];
int le ;
while((le=fis.read(bs))!=-1) {
os.write(bs, 0, le);
}
//方法
socket.shutdownOutput(); //输出完成
//接收服务端的数据
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
while((len=is.read(bytes))!=-1) {
String s = new String(bytes,0,len);
System.out.println(s);
}
is.close();
os.close();
socket.close();
}
//服务端
@Test
public void server() throws IOException {
ServerSocket ss=new ServerSocket(8888);
Socket socket = ss.accept(); //监听客户端是否有消息
FileOutputStream fis = new FileOutputStream(new File("c.txt"));
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
while((len=is.read(bytes))!=-1) { //阻塞
fis.write(bytes, 0, len);
}
/
//向客户端发数据
OutputStream os = socket.getOutputStream();
os.write("好的,我收到了!".getBytes());
os.close();
is.close();
socket.close();
ss.close();
}
}
1.4 UDP网路协议通讯
DatagramSocket: 此类表示用于发送和接收数据报套接字
DatagramPacket: 封装了UDP数据报,在数据报中包含了发送端和接收端的IP和端口号。
UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
public class TestUDP2 {
//发送方
@Test
public void client() throws Exception {
DatagramSocket ds = new DatagramSocket();
byte[] bytes = "你好,我是客户端".getBytes();
DatagramPacket dp = new DatagramPacket(bytes, 0, bytes.length,
InetAddress.getLocalHost(), 8989);
//发送
ds.send(dp);
ds.close();
}
//接收方
@Test
public void server() throws Exception {
DatagramSocket ds = new DatagramSocket(8989);
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,0,bytes.length);
//接收方法
ds.receive(dp);
String s =new String(dp.getData(),0,dp.getLength());
System.out.println(s);
ds.close();
}
}
UDP传送文件
public class TestUDP2 {
//发送方
@Test
public void client() throws Exception {
DatagramSocket ds = new DatagramSocket();
//本地读取文件
FileInputStream fis = new FileInputStream(new File("a.txt"));
byte[] bytes = new byte[fis.available()];
fis.read(bytes); //读到字节数组中
DatagramPacket dp = new DatagramPacket(bytes, 0, bytes.length,
InetAddress.getLocalHost(), 8989);
//发送
ds.send(dp);
//释放资源
fis.close();
ds.close();
}
//接收方
@Test
public void server() throws Exception {
DatagramSocket ds = new DatagramSocket(8989);
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,0,bytes.length);
//接收方法
ds.receive(dp);
//输出磁盘某一位置
FileOutputStream fos = new FileOutputStream(new File("b.txt"));
fos.write(dp.getData(), 0, dp.getLength());
//释放资源
fos.close();
ds.close();
}
}
1.5 URL编程
-
URL:统一资源定位符 或叫网络一资源
-
组成:<传输协议>://<主机名>:<端口号 http默认80>/<文件名>
-
openStream() --读
打开与此 URL ,并返回一个 InputStream ,以便从该连接读取。
-
openConnection() —可以读,可以写(下载)
返回一个URLConnection实例,表示与URL引用的远程对象的URL 。
-
getInputStream()
返回从此打开的连接读取的输入流。
public class TestUrl {
@Test
public void test1() throws Exception {
URL url = new URL("http://127.0.0.1:8080/examples/1.txt");
//URL url1 = new URL("http://img.redocn.com/sheji/20141219/zhongguofengdaodeliyizhanbanzhijing_3744115.jpg")
InputStream is = url.openStream();
byte[] bytes =new byte[1024];
int len;
while((len=is.read(bytes))!=-1) {
String s = new String(bytes,0,len);
System.out.println(s);
}
is.close();
}
@Test
public void test2() throws Exception {
URL url1 = new URL("http://img.redocn.com/sheji/20141219/zhongguofengdaodeliyizhanbanzhijing_3744115.jpg");
URLConnection conn = url1.openConnection();
InputStream is = conn.getInputStream();
//写当前d:/abc.jpg
FileOutputStream fos = new FileOutputStream(new File("d:/abc.jpg"));
byte[] bytes =new byte[1024];
int len;
while((len=is.read(bytes))!=-1) {
fos.write(bytes, 0, len);
}
System.out.println("成功");
fos.close();
is.close();
}
}
1.6 动态代理(静态代理)
public class DynamicProxy {
public static void main(String[] args) {
RealSubject real = new RealSubject();
MyProxy myproxy = new MyProxy();
Object obj = myproxy.bind(real); //初始化了被代理对象 obj它就是代理对象
Subject sub = (Subject)obj; //接口subject
sub.action();
System.out.println("===========================");
Object bind = myproxy.bind(new RealObject());
Interface i =(Interface)bind; //接口Interface
i.action();
}
}
//
interface Subject{
void action();
}
//被代理类
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("被代理类的行为");
}
}
//代理类的处理类,调用代理对象的方法时会自动调用invoke方法
class MyProxy implements InvocationHandler{
Object obj=null; //被代理类对象的声明
//声明一个方法1.实例化被 代理对象 2 返回一个代理对象
public Object bind(Object obj) {
//实例化被 代理对象
this.obj = obj;
//返回代理对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("1111111111111");
Object o = method.invoke(obj, args); //通过反射调用被代理类的方法
System.out.println("2222222222222");
return o;
}
}
1.7 死锁
同步块,同步方法目的是实现线程安全
如果synchronized关键嵌套不当,就会引起死锁
public class TestDeadThread {
static Object obj1 = new Object();
static Object obj2 = new Object();
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
synchronized(obj1) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1的obj1");
synchronized (obj2) {
System.out.println("线程1的obj2");
}
}
}}.start();
new Thread() {
@Override
public void run() {
synchronized(obj2) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程2的obj2");
synchronized (obj1) {
System.out.println("线程2的obj1");
}
}
}}.start();
}
}