java之网络编程
------- android培训、java培训、期待与您交流! ---------
网络模型
OSI参考模型
TCP/IP参考模型
图形解析:
网络通讯要素:
IP地址:网络中设备的标识,不易记忆,可用主机名;本地回环地址:127.0.0.1,主机名:localhost
端口号:用于标识进程的逻辑地址,不同进程的标识;有效端口:0-65535,其中0-1024被系统使用或是保留端口。
传输协议:即通讯的规则,常见协议有:TCP UDP
TCP和UDP的区别:
UDP(聊天软件,视频会议,桌面共享等常用,如QQ)
1.将数据及源和目的封装成数据包,不需要建立连接
2.每个数据包的大小限制在64k内
3.因无连接,是不可靠协议
4.不需要建立连接,速度快
TCP(下载软件常用,如迅雷)
1.建立连接,形成传输数据的通道
2.在连接中可以进行大数据量传输
3.通过三次握手完成连接,是可靠协议
4.必须建立连接,效率会稍低
UDP传输
Socket
1.Socket就是为网络服务提供的一种机制。
2.通信的两端都有Socket
3.网络通信其实就是Socket间的通信
4.数据在两个Socket间通过IO传输
1.使用到DatagramSocket与DatagramPacket
DatagramSocket:用于建立发送端,接收端。
DatagramPacket:用于封装数据包。
代码实现过程:
- /*
- * 建立发送端
- * 思路
- * 1,建立udpsocket服务
- * 2,提供数据,并将数据封装到数据包中
- * 3,secket服务的发送功能,将数据包发送出去
- * 4,关闭资源
- */
- public class UdpSend {
- public static void main(String[] args) throws IOException {
- // 1,创建upd服务。通过DatagramSocket对象
- DatagramSocket ds = new DatagramSocket(/* 6886 */);// 可以指定一个端口,也可不写则由系统随机分配
- // 2,确定数据,并封装成数据包
- byte[] buf = "Hi,你好".getBytes();
- DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress
- .getByName("127.0.0.1"), 10000);// 构造数据报包,用来将长度为 length
- // 的包发送到指定主机上的指定端口号。
- // 3,通过Socket服务,将已有的数据包发送出去。通过send方法。
- ds.send(dp);
- // 4,关闭资源
- ds.close();
- }
- }
- /*
- * 定义udp的接收端
- * 思路:
- * 1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识
- * 方便于明确那些数据过来,应用程序可以处理
- * 2,定义一个数据包,因为要存储收到的字节数据。
- * 因为数据包对象中有更多功能可能可以提取字节数据中的不同数据信息
- * 3,通过Socket服务的receive方法将收到的数据存入一定义好的数据包中。
- * 4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
- * 5,关闭资源。
- */
- class UdpRece {
- public static void main(String[] args) throws IOException {
- // 1,创建udp Socket ,建立端点
- DatagramSocket ds = new DatagramSocket(10000);
- // 2,定义数据包,用于存储数据
- byte[] buf = new byte[1024 * 64];
- DatagramPacket dp = new DatagramPacket(buf, buf.length);
- // 3,通过服务的receive方法将收到数据存入数据包中。
- ds.receive(dp);
- // 4,通过数据包的方法获取其中的数据。
- String ip = dp.getAddress().getHostAddress();
- String data = new String(dp.getData(), 0, dp.getLength());
- int port = dp.getPort();// 返回发送端主机的端口号
- System.out.println(ip + "::" + data + "::" + port);
- // 5,关闭资源
- ds.close();
- }
- }
/*
* 建立发送端
* 思路
* 1,建立udpsocket服务
* 2,提供数据,并将数据封装到数据包中
* 3,secket服务的发送功能,将数据包发送出去
* 4,关闭资源
*/
public class UdpSend {
public static void main(String[] args) throws IOException {
// 1,创建upd服务。通过DatagramSocket对象
DatagramSocket ds = new DatagramSocket(/* 6886 */);// 可以指定一个端口,也可不写则由系统随机分配
// 2,确定数据,并封装成数据包
byte[] buf = "Hi,你好".getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress
.getByName("127.0.0.1"), 10000);// 构造数据报包,用来将长度为 length
// 的包发送到指定主机上的指定端口号。
// 3,通过Socket服务,将已有的数据包发送出去。通过send方法。
ds.send(dp);
// 4,关闭资源
ds.close();
}
}
/*
* 定义udp的接收端
* 思路:
* 1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识
* 方便于明确那些数据过来,应用程序可以处理
* 2,定义一个数据包,因为要存储收到的字节数据。
* 因为数据包对象中有更多功能可能可以提取字节数据中的不同数据信息
* 3,通过Socket服务的receive方法将收到的数据存入一定义好的数据包中。
* 4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
* 5,关闭资源。
*/
class UdpRece {
public static void main(String[] args) throws IOException {
// 1,创建udp Socket ,建立端点
DatagramSocket ds = new DatagramSocket(10000);
// 2,定义数据包,用于存储数据
byte[] buf = new byte[1024 * 64];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
// 3,通过服务的receive方法将收到数据存入数据包中。
ds.receive(dp);
// 4,通过数据包的方法获取其中的数据。
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(), 0, dp.getLength());
int port = dp.getPort();// 返回发送端主机的端口号
System.out.println(ip + "::" + data + "::" + port);
// 5,关闭资源
ds.close();
}
}
测试的时候,先运行接收端UdpRece,再运行UdpSend。反过来的话就会导致发送端发送的数据丢失。
2.聊天程序的实现过程
需求:编写一个聊天程序,有收数据的部分和发数据的部分,这两部分需要同时执行,那就需要用到多线程技术,一个线程控制接收,
一个线程控制发送。
分析:
因为接收和发送动作是不一致的,所以要定义两个run方法,
而且这两个方法要封装到不同的类中。
示例代码:
- import java.io.*;
- import java.net.*;
- class Send implements Runnable
- {
- privateDatagramSocket ds ;
- publicSend(DatagramSocket ds)
- {
- this.ds= ds;
- }
- publicvoid run()
- {
- try
- {
- BufferedReaderbufr =
- newBufferedReader(new InputStreamReader(System.in));
- Stringline = null;
- while((line =bufr.readLine())!= null)
- {
- if("886".equals(line))
- break;
- byte[]buf = line.getBytes();
- DatagramPacketdp=newDatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10003);
- ds.send(dp);
- }
- }
- catch(Exception e)
- {
- thrownew RuntimeException("发送端失败");
- }
- }
- }
- class Rece implements Runnable
- {
- privateDatagramSocket ds ;
- publicRece(DatagramSocket ds)
- {
- this.ds= ds;
- }
- publicvoid run()
- {
- try
- {
- while(true)
- {
- byte[]buf = new byte[1024*64];
- DatagramPacketdp = new DatagramPacket(buf,buf.length);
- ds.receive(dp);
- Stringip = dp.getAddress().getHostAddress();
- Stringdata = new String(dp.getData(),0,dp.getLength());
- System.out.println(ip+":"+data);
- }
- }
- catch(Exception e)
- {
- thrownew RuntimeException("接收端失败");
- }
- }
- }
- class ChatDemo
- {
- publicstatic void main(String[] args) throws Exception
- {
- DatagramSocketsendSocket = new DatagramSocket();
- DatagramSocketreceSocket = new DatagramSocket(10003);
- newThread(new Send(sendSocket)).start();
- newThread(new Rece(receSocket)).start();
- }
- }
TCP传输
使用到Socket(客户端)和ServerSocket(服务器端)
客户端:
客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。
连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(),getOutputStream()获取即可。
与服务端通讯结束后,关闭Socket。
服务端:
服务端需要明确它要处理的数据是从哪个端口进入的。
当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
当该客户端访问结束,关闭该客户端。
需求:定义TCP服务端,接收数据并打印在控制台上。
示例代码:
- import java.io.*;
- import java.net.*;
- class TcpServer
- {
- publicstatic void main(String[] args)throws Exception
- {
- //建立服务端Socket服务,并监听一个端口
- ServerSocketss = new ServerSocket(10004);
- //通过accept方法获取连接过来的客户端对象。
- Sockets = ss.accept();//accept是一个阻塞式方法
- //获取客户端的IP地址
- Stringip = s.getInetAddress().getHostAddress();
- System.out.println(ip+".....connected");
- //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
- InputStreamis = s.getInputStream();
- byte[]buf = new byte[1024];
- intlen = is.read(buf);
- Stringdata = new String(buf,0,len);
- System.out.println(data);
- s.close();//关闭客户端
- ss.close();//关闭服务端,这是一个可选操作。
- }
- }
需求:上传图片
示例代码:
- //客户端
- import java.io.*;
- import java.net.*;
- class UploadPicClient
- {
- publicstatic void main(String[] args) throws IOException
- {
- //1.创建Socket服务端点
- Sockets = new Socket("localhost",50005);
- //2.读取客户端已有的图片数据
- FileInputStreamin = new FileInputStream("c:\\1.png");
- //3.通过socket输出流将数据发给服务端
- OutputStreamout = s.getOutputStream();
- byte[]buf = new byte[1024];
- intlen = 0 ;
- while((len= in.read(buf))!=-1)
- {
- out.write(buf,0,len);
- }
- //告诉服务器数据写完了。
- s.shutdownOutput();
- //4.通过Socket输入流读取服务端反馈的信息
- InputStreamis = s.getInputStream();
- byte[]bufIn = new byte[1024];
- intnum = is.read(bufIn);
- System.out.println(newString(bufIn,0,num));
- //5.关闭Socket服务
- s.close();
- in.close();
- }
- }
- //服务端
- class UploadPicServer
- {
- publicstatic void main(String[] args) throws IOException
- {
- //1.创建Socket服务,并监听50005端口
- ServerSocketss = new ServerSocket(50005);
- //2.通过accept方法获取连接进来的客户端对象
- Sockets = ss.accept();
- Stringip = s.getInetAddress().getHostAddress();
- System.out.println(ip+".....connected");
- //获取客户端发送过来的数据,使用客户端对象的读取流来读取数据。
- InputStreamin = s.getInputStream();
- //创建一个文件输出流对象,并指定数据存放目的地
- FileOutputStreamout = new FileOutputStream("d:\\sever.png");
- byte[]buf = new byte[1024];
- intlen = 0 ;
- while((len= in.read(buf))!=-1)
- {
- out.write(buf,0,len);
- }
- //通过客户端输出流反馈作息给客户端
- OutputStreamos = s.getOutputStream();
- os.write("上传图片成功!!".getBytes());
- //关闭服务
- out.close();
- s.close();
- ss.close();
- }
- }
需求:自定义一个服务器
示例代码:
- import java.io.*;
- import java.net.*;
- class ServerDemo
- {
- publicstatic void main(String[] args) throws Exception
- {
- ServerSocketss = new ServerSocket(14000);
- while(true)
- {
- Sockets = ss.accept();
- newThread(new ServerThread(s)).start();
- }
- }
- }
- class ServerThread implements Runnable
- {
- privateSocket s ;
- ServerThread(Sockets)
- {
- this.s= s;
- }
- publicvoid run()
- {
- System.out.println(s.getInetAddress().getHostAddress());
- try
- {
- InputStreamin = s.getInputStream();
- byte[]buf = new byte[1024];
- intlen = 0;
- while((len= in.read(buf))!=-1)
- {
- System.out.println(newString(buf,0,len));
- }
- PrintWriterout = new PrintWriter(s.getOutputStream(),true);
- out.println("<b>客户端你好");
- s.close();
- }
- catch(Exception e)
- {
- thrownew RuntimeException("failed");
- }
- }
- }
URL
类URL
代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
常用方法:
getContent() |
|
getContent(Class[] classes) |
|
int |
getDefaultPort() |
getFile() |
|
getHost() |
|
getPath() |
|
int |
getPort() |
getProtocol() |
|
getQuery() |
URLCollection
它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:
openConnection() |
connect() |
对影响到远程资源连接的参数进行操作。 |
与资源交互;查询头字段和内容。 |
---------------------------->
时间
- 通过在 URL 上调用 openConnection 方法创建连接对象。
- 处理设置参数和一般请求属性。
- 使用 connect 方法建立到远程对象的实际连接。
- 远程对象变为可用。远程对象的头字段和内容变为可访问。
使用以下方法修改设置参数:
- setAllowUserInteraction
- setDoInput
- setDoOutput
- setIfModifiedSince
- setUseCaches
使用以下方法修改一般请求属性:
- setRequestProperty
在建立到远程对象的连接后,以下方法用于访问头字段和内容:
- getContent
- getHeaderField
- getInputStream
- getOutputStream
某些头字段需要经常访问。以下方法:
- getContentEncoding
- getContentLength
- getContentType
- getDate
- getExpiration
- getLastModifed
------- android培训、java培训、期待与您交流! ---------