------- android培训、java培训、期待与您交流! ----------
网络通信三大要素
IP地址,端口号传输协议
先说一下网络通信三大要素的概念:
1.IP地址:你要发送数据到指定的位子首先你要找到对方的位子,也就是对 方在网络上的IP地址,IP地址就相当于对方机器的名字,每一台连接网络 的机器都有自己一个与别人不同的IP地址。
2.端口号:数据要发送到对方指定的程序上,因为不同的应用能接收的数据 是不同的,只有相同的应用才能看的懂你发过来的数据,电脑为了区分这些 应用程序。所以要给这些应用程序用数据进行一个标识,用来区分不同的应 用程序。我们一般把这些程序称之为端口。
每一个网络应用程序都会有一个不同的端口也是必须有的(端口号只能是0 到65535 并且0到1024是给系统保留的)
3.传输协议:两个网络应用程序要进行通讯的话,还需要定义一个通讯的规 则,我们把这个规则称为协议。之所以一个应用程序可以使很多人进行通讯, 就是因为他们使用了同一个通信协议。目前用的最多的就是TCP/IP,这是以 个国际组织定义的通用协议,又能在局域网使用,也可以再广域网使用。这是一个非常强大的协议。并且它是默认的广域网协议。
网络模型
OSI参考模型
TCP/IP参考模型
Java中的IP对象
import java.net.*;
class IPDemo
{
publicstatic void main(String[] args)throws Exception
{
//通过名称来获取一个IP对象
InetAddressia=InetAddress.getByName("www.baidu.com");
System.out.println(ia.getHostAddress());//获取主机地址
System.out.println(ia.getHostName());//获取主机名
}
}
目前网络上最常见用的最多的2种协议是TCP和UDP2种
TCP的特点:
建立连接,形成传输数据的通道
在连接中进行大量数据传输
通过三次握手完成链接,是可靠协议
必须建立连接,效率会稍低
UDP的特点
将数据及源和目的封装在数据包中,不需要建立连接
每个数据大小限制在64K内
因无连接,是不可靠协议
不需要建立连接,速度快
Socket(套接字)
1.Socket就是为网络服务提供的一种机制
2.通信的两端都有Socket
3.网络通信其实就是Socket间的通信
4.数据在两个Socket间通过IO传输
Udp发送端
1)只要是网络传输,必须有socket,
2)数据一定要封装到数据包中,数据包中包括目的地址,端口,数据等信息
DatagramSocket对象封装了udp传输协议的socket对象
DatagramPacket通过这个对象的方法,就可以获取到数据包中的各种信息
需求:通过udp传输方式,将一段文字数据发送出去
1,建立updsocket服务。
2,提供数据,并将数据封装到数据包中。
3,通过socket服务的发送功能,将数据包发出去。
4,关闭资源。
import java.net.DatagramPacket;
import java.net.DatagramSocket;
class Udpsend
{
publicstatic void main(String[] args)throws Exception
{
DatagramSocketds=new DatagramSocket(8888);
byte[]buf="Udp lai le".getBytes();
DatagramPacket dp=newDatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),1000);
ds.send(dp);
ds.close();
}
}
Udp接收端
需求:
定义一个应用程序,用于接收udp协议传输的数据并处理的。
1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络 应用程序定义数字标识。方便于明确哪些数据过来该应用程序可以处理。
2,定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
5,关闭资源。
import java.net.DatagramPacket;
import java.net.DatagramSocket;
class UdpRece
{
publicstatic void main(String[] args) throws Exception
{
//1,创建udp socket,建立端点。
DatagramSocketds = new DatagramSocket(10000);//指定监听窗口
while(true)
{
//2,定义数据包。用于存储数据。
byte[]buf = new byte[1024];
DatagramPacketdp = new DatagramPacket(buf,buf.length);
//3,通过服务的receive方法将收到数据存入数据包中。
ds.receive(dp);//阻塞式方法。
//4,通过数据包的方法获取其中的数据,比如ip、端口、数据等
Stringip = dp.getAddress().getHostAddress();//获取字符串ip
Stringdata = new String(dp.getData(),0,dp.getLength());
intport = dp.getPort();//获取端口
System.out.println(ip+"::"+data+"::"+port);
}
//5,关闭资源
ds.close();
}
}
练习一
需求:通过键盘录入,获取要发送的信息
import java.net.*;
import java.io.*;
class Udpsend2
{
publicstatic void main(String[] args)throws Exception
{
DatagramSocketds=new DatagramSocket();
BufferedReaderbufr=new BufferedReader(new InputStreamReader(System.in));
Stringline=null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
byte[]buf=line.getBytes();
DatagramPacketdp=new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10001);
ds.send(dp);
}
ds.close();
}
}
class Udprece2
{
publicstatic void main(String[] args)throws Exception
{
DatagramSocketds=new DatagramSocket(10001);
while(true)
{
byte[]buf=new byte[1024];
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);
}
}
}
练习二
需求:编写一个聊天程序
import java.io.*;
import java.net.*;
class Send implements Runnable
{
privateDatagramSocket ds;
publicSend(DatagramSocket ds)
{
this.ds= ds;
}
publicvoid run()
{
try
{
BufferedReaderbufr =
new BufferedReader(newInputStreamReader(System.in));
Stringline = null;
while((line=bufr.readLine())!=null)
{
byte[]buf = line.getBytes();
DatagramPacketdp = newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1. 255"),10002);
ds.send(dp);
if("886".equals(line))
break;
}
}
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];
DatagramPacket dp = newDatagramPacket(buf,buf.length);
ds.receive(dp);
Stringip = dp.getAddress().getHostAddress();
Stringdata = new String(dp.getData(),0,dp.getLength());
if("886".equals(data))
{
System.out.println(ip+"....离开聊天室");
break;
}
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(10002);
newThread(new Send(sendSocket)).start();
newThread(new Rece(receSocket)).start();
}
}
Tcp传输
Socket和ServerSocket
建立客户端Socket和服务端ServerSocket
建立连接后,通过Socket中的IO流进行数据的传输
关闭Socket
同样,客户端与服务端是两个独立的应用程序
Tcp客户端
客户端,
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。
因为tcp是面向连接的。所以在建立socket服务时,
就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
步骤如下:
1.创建客户端的socket服务,指定目的主机和端口
2.为了发送数据,应该获取socket中的输出流
3.然后通过输出流write方法把数据放到socket的输出流里
4.关闭资源
需求:给服务端发送给一个文本数据。
代码如下:
import java.io.*;
import java.net.*;
class TcpClient
{
publicstatic void main(String[] args) throws Exception
{
//创建客户端的socket服务。指定目的主机和端口
Sockets = new Socket("192.168.1.254",10003);
//为了发送数据,应该获取socket流中的输出流。
OutputStreamout = s.getOutputStream();
out.write("您好".getBytes());
s.close();
}
}
Tcp服务端
服务端:
1,建立服务端的socket服务。ServerSocket();并监听一个端口。
2,获取连接过来的客户端对象。
通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。
3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取 到该客户端对象的读取流来读取发过来的数据,并打印在控制台。
4,关闭服务端。(可选)
步骤如下:
1,建立socket服务指定要连接的主机和端口
2,获取socket流中的输出流 将数据写到该流中通过网络发送给服务端
3,获取socket流中的输入流将服务端反馈的信息获取
4,关闭客户端资源
需求:定义端点接收数据并打印在控制台上。
代码如下:
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
class TcpServer
{
publicstatic void main(String[] args) throws Exception
{
//建立服务端socket服务。并监听一个端口。
ServerSocketss = new ServerSocket(10003);
//通过accept方法获取连接过来的客户端对象。
while(true)
{
Sockets = ss.accept();
Stringip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");
//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
InputStreamin = s.getInputStream();
byte[]buf = new byte[1024];
intlen = in.read(buf);
System.out.println(newString(buf,0,len));
s.close();//关闭客户端.
}
}
}
练习一:
需求:上传图片。
客户端。
1,服务端点。
2,读取客户端已有的图片数据。
3,通过socket输出流将数据发给服务端。
4,读取服务端反馈信息。
5,关闭。
import java.io.*;
import java.net.*;
class SocketPic
{
publicstatic void main(String[] args) throws Exception
{
if(args.length!=1)
{
System.out.println("请选择一个.jpg格式的图片");
return;
}
Filefile=new File(args[0]);
if(!(file.exists()&&file.isFile()))
{
System.out.println("该文件有问题,要么不存在。要不有问题");
return;
}
if(file.getName().endsWith(".jpg"))
{
System.out.println("图片格式不正确");
return;
}
if(file.length()>1024*5)
{
System.out.println("图片太大");
return;
}
Sockets=new Socket("127.0.0.1",10007);
FileInputStreamfis=new FileInputStream(file);
OutputStreamout=s.getOutputStream();
byte[]buf=new byte[1024];
intlen=0;
while((len=fis.read(buf))!=-1)
{
out.write(buf,0,len);
}
//告诉服务端数据已写完
s.shutdownOutput();
InputStreamin=s.getInputStream();
byte[]bufin=new byte[1024];
intnum=in.read(bufin);
System.out.println(newString(bufin,0,num));
s.close();
fis.close();
}
}
/*服务端可以让多个客户端同时并发访问服务端。那么服务端就将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。
*/
class PicThread implements Runnable
{
privateSocket s;
PicThread(Sockets)
{
this.s=s;
}
publicvoid run()
{
intcount=1;
Stringip=s.getInetAddress().getHostAddress();
try
{
System.out.println(ip+"....connect");
InputStreamin=s.getInputStream();
Filefile=new File(ip+"("+(count)+")"+".jpg");
while(file.exists())
file=newFile(ip+"("+(count++)+")"+".jpg");
FileOutputStreamfos=new FileOutputStream(file);
byte[]buf=new byte[1024];
intlen=0;
while((len=in.read())!=-1)
{
fos.write(buf,0,len);
}
OutputStreamout=s.getOutputStream();
out.write("上传成功".getBytes());
s.close();
fos.close();
}
catch(Exception e)
{
thrownew RuntimeException(ip+"上传失败");
}
}
}
class ServerSocketPic
{
publicstatic void main(String[] args) throws Exception
{
ServerSocketss=new ServerSocket(10007);
while(true)
{
Sockets=ss.accept();
newThread(new PicThread(s)).start();
}
}
}
URL
URL代表一个统一资源定位符
URL的一些方法:
StringgetFile()
获取此 URL的文件名。
StringgetHost()
获取此 URL的主机名(如果适用)。
StringgetPath()
获取此 URL的路径部分。
intgetPort()
获取此 URL的端口号。
StringgetProtocol()
获取此 URL的协议名称。
StringgetQuery()
获取此 URL的查询部
如果没有端口getPort()返回-1;系统默认是80
URLConnection conn = url.openConnection();表示到URL所引用的远程对象的连接;
InputStream in = conn.getInputStream();由此可见,URLConnection类把Socket类中的getInputStream()封装起来了;
补充知识点:
InetSocketAddress(IP+端口)
InetAddress(IP)
ServerSocket(int port)
ServerSocket(int port,int backlog);指定队列
域名解析
想要将主机名翻译成ip地址,需要域名解析DNS
可以用映射关系蒙蔽网站。
------- android培训、java培训、期待与您交流! ----------