1.通信要素:
1.找到对方IP
2.数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。
为了方便称呼这个数字,叫做 端口,逻辑端口。
3.定义通信规则,这个通讯规则成为协议。国际组织定义了通用协议 TCP/IP。
2.一些基本方法:
InetAddress i = InetAddress.getLocalHost();获取主机对象
i.toSting();返回主机名和主机IP地址
i.getHostAddress();获取主机IP地址
i.getHostName();获取主机名
*如何获取其他地址的主机对象。
InetAddress ia = InetAddress.getByName(String IP);例如:InetAddress.getByName("www.baidu.com");
3.UDP特点:
1.将数据及源和目的和封装成数据包中,不需要建立连接;
2.每个数据包的大小限制在64K内;
3.因无连接,是不可靠协议;
4.不需要建立连接,速度快。
*简单小例子:
*需求:通过udp传输方式,将一段文字数据发送出去。
思路:
1.建立udpSocket服务;
2.提供数据,并将数据封装到数据包中;
3.通过socket服务的发送功能,将数据包发出去;
4.关闭资源。
*发送端:
public class UdpSend{
public static void main(String[] args)throws Exception{
//1.创建udp服务,通过DatagramSocket对象。
DatagramSocket ds = new DatagramSocket();
//2.确定数据,并封装成数据包,DatagramPacket(byte[] buf, int length, InetAddress address, int port)
byte[] buf = "udp ge men lai la".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10000);
//3.通过socket服务,将已有的数据包发送出去,通过send方法。
ds.send(dp);
//4.关闭资源。
ds.close();
}
}
*需求:定义一个应用程序,用于接收udp协议传输的数据并处理。
思路:
1.定义udpsocket服务;
2.定义一个数据包,因为要存储接收到的字节数据,因为数据包对象有更多的功能可以提取字节数据中的不同数据信息;
3.通过socket服务的receive方法将收到的数据存入已定义好的数据包中;
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。
5.关闭资源。
*接收端:
public class UdpReceive{
public static void main(String[] args)throws Exception{
//1.创建udp服务,通过DatagramSocket对象。
DatagramSocket ds = new DatagramSocket(10000);
//2.定义数据包,用于存储数据
byte[] buf = new byte[1024];
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();
}
}
*聊天程序:
编写一个聊天程序,有收数据的部分,和发数据的部分。这两部分需要同时进行。
那就需要用到多线程技术,一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法,而且这两个方法要封装到不同的类中。
class Send implements Runnable{
private DatagramSocket ds;
public Send(DatagramSocket ds){
this.ds = ds;
}
public void run(){
try{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine())!=null){
if("886".equals(line))
break;
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.255"),10002);
ds.send(dp);
}
}catch(Exception e){
throw new RuntimeException("发送端失败");
}
}
}
class Rece implements Runnable{
private DatagramSocket ds;
public Rece(DatagramSocket ds){
this.ds = ds;
}
public void run(){
try{
while(true){
byte[] buf =new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+data);
}
}catch (Exception e){
throw new RuntimeException("接收端失败");
}
}
}
class ChatDemo{
public static void main(String[] args)throws Exception{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10002);
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}
4.TCP特点:
1.建立连接,形成传输数据的通道;
2.在连接中进行大数据量传输;
3.通过三次握手完成连接,是可靠协议;
4.必须建立连接,效率会稍低。
*客户端:
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机,因为tcp是面向连接的,所以在建立socket服务时,
就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
步骤:
1.创建Socket服务,并指定要连接的主机和端口。
2.获取socket流中的输出流,将数据写到该流中,通过网络发送给服务端。
3.获取socket流中的输入流,将服务端反馈的数据获取到,并打印。
4.关闭客户端资源。
class TcpClient{
public static void main(String[] args)throws Exception{
//创建客户端socket服务,指定目的主机和端口
Socket s = new Socket("127.0.0.1",10003);
//为了发送数据,应该获取socket流中的输出流
OutputStream out = s.getOutputStream();
out.write("tcp ge men lai le".getBytes());
s.close();
}
}
需求:定义端点接收数据并打印在控制台上
服务端:
1.建立服务端的socket对象,ServerSocket();并监听一个端口。
2.获取连接过来的客户端对象,通过ServerSocket的accept方法,没有连接就会等,所以这个方法是阻塞的。
3.客户端如果发过来数据,那么服务端要是用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。
4.关闭服务端(可选,例如大型网站,不可能访问完就关闭)
class TcpServer{
public static void main(String[] args)throws Exception{
//建立服务端socket服务,并监听一个端口。
ServerSocket ss = new ServerSocket(10003);
//通过accept方法获取连接过来的客户端对象
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connnected");
// 获取客户端发送过来的数据,呢么要是用客户端对象的读取流对象读取数据。
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
s.close();//关闭客户端,服务端有可能会把访问完的客户断开连接。
}
}
对于结束标记的问题:Socket对象中有结束输出流方法shutdownOutput(); 禁用此套接字的输出流。
通常情况下,服务端是多线程服务的,因为客户不止一个,不可能每次只访问一个。
如下循环模式:
//循环接收客户端,每接收一个客户端就开启一个线程为其服务。
while(true){
Socket s = ss.accept();
new Thread(new PicThread(s)).start();
}
5.自定义服务端,客户端为浏览器:
public class ServerDemo
{
public static void main(String[] args)throws Exception{
ServerSocket ss = new ServerSocket(11000);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress()+"...connect");
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("客户端你好");
s.close();
ss.close();
}
}
6.URL 类:用于解析url的类
常用方法:
url.getProtocol();获取协议
url.getHost();获取主机
url.getPort();获取端口
url.getPath();
url.getFile();
url.getQuery();获取此url的查询部分
URL url = new URL("http://192.168.1.254:8080/myweb/demo.html");
URLConnection conn = url.openConnection();//内部封装与服务端的连接。并具备解析url功能
//此后便可使用URLConnection对象获取数据
InputStream in = conn.getInputStream();
7.域名解析原理:
假如访问www.sina.com.cn主页,那么是如何连接到服务器的呢?
首先要将主机名翻译成ip地址,需要域名解析,DNS域名解析服务器。
用户访问后,首先要到公网找域名解析服务器,找sina主机名对应的ip地址。找到后,DNS服务器将ip域名返回
用户在通过ip访问主机。