------- android培训、java培训、期待与您交流! ----------
网络编程
TCP连接建立的时候3次握手,断开连接的4次握手的具体过程:
建立连接采用的3次握手协议,具体是指:
第一次握手是客户端connect连接到server,server accept client的请求之后,向client端发送一个消息,相当于说我都准备好了,你连接上我了,这是第二次握手,第3次握手就是client向server发送的,就是对第二次握手消息的确认。
之后client和server就开始通讯了。
断开连接的4次握手,具体如下:
断开连接的一端发送close请求是第一次握手,另外一端接收到断开连接的请求之后需要对close进行确认,发送一个消息,这是第二次握手,发送了确认消息之后还要向对端发送close消息,要关闭对对端的连接,这是第3次握手,而在最初发送断开连接的一端接收到消息之后,进入到一个很重要的状态time_wait状态,最后一次握手是最初发送断开连接的一端接收到消息之后。对消息的确认。
网络编程概述
TCP和UDp特点:
UDP特点:
将数据及源和目的封装成数据包中,不需要建立连接。
每个数据报的大小在限制64k内。
因无连接,是不可靠协议。
不需要建立连接,速度快。
TCP特点:
建立连接,形成传输数据的通道。
在连接中进行大数据量的传输。
通过三次握手完成连接,是可靠协议。
必须建立连接,效率会稍低。
Socket
Socket就是为网络服务提供的一种机制。
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
UDP传输
DatagramSocket与DatagramPacket。
建立发送端,接收端。
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
发送端与接收端是两个独立的运行程序。
例:
InetAddress i = InetAddress.getLocalHost();
System.out.println(i.toString());
System.out.println("adress:"+i.getHostAddress());
System.out.println("name:"+i.getHostName());
练习:
需求:通过UDP传输方式,将一段文字数据发送出去。
定义一个udp发送端。
思路:
1、建立udpsocket服务。
2、提供数据,并将数据封装到数据包中。
3、通过socket服务的发送功能,将数据包发出去。
4、关闭资源。
import java.net.*;
class UdpSend
{
publicstatic void main(String[] args) throws Exception
{
//1创建UDP服务,通过DatagramSocket对象。
DatagramSocketds = new DatagramSocket();
//2确定数据,并封装成数据包,DatagramPacket
byte[]buf = "udp ge men lai le".getBytes();
DatagramPacket dp = newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.104"),1000);
//3通过Scoket服务,将已有的数据包发送出去。通过send方法
ds.send(dp);
//4 关闭资源。
ds.close();
}
}
必要掌握一下。
编写一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。
import java.net.*;
import java.io.*;
class Send implements Runnable
{
privateDatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds= ds;
}
publicvoid run()
{
try
{
BufferedReaderbufr = new BufferedReader(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("192.168.1.255"),10002);
ds.send(dp);
}
}
catch(Exception e)
{
thrownew RuntimeException("发送端失败。");
}
}
}
class Rece implements Runnable
{
privateDatagramSocket ds;
public Rece(DatagramSocket ds)
{
this.ds= ds;
}
publicvoid run()
{
try
{
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);
}
}
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传输图例:
TCP传输。
Socket和ServerSocket
建立客户端和服务器端。
建立连接后,通过Socket中的IO流进行数据的传输。
关闭Socket。
同样,客户端与服务器端是两个独立的应用程序。
练习:演示Tcp传输。
思路:
1、Tcp分客户端和服务端。
2、客户端对应的对象是Socket。
服务端对应的对象是ServerSocket。
客户端:
通过查阅Scoket对象,发现在该对象建立时,就可以去连接指定主机。
因为Tcp是面向连接的,所以在建立Socket服务时,
就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输。
需求:
给服务端发送一个文本数据。
步骤:
1、创建Socket服务,并指定要连接的主机和端口。
import java.io.*;
import java.net.*;
class TcpClient
{
publicstatic void main(String[] args) throws Exception
{
//创建客户端的Socket服务,指定目的主机和端口。
Sockets = new Socket("192.168.1.104",10004);
//为了发送数据,应该获取Socket流中的输出流。
OutputStreamout = s.getOutputStream();
out.write("tcpge men lai le".getBytes());
s.close();
}
}
需求:定义端点接收数据并打印在控制台上
服务端:
1、建立服务端的Socket服务。ServerSocket();
并监听一个端口。
2、获取连接过来的客户端对象。
通过ServerSocket的accept方法。没有连接就是等。所以这个方法是阻塞式的。
3、客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。
并打印在控制台。
4、关闭服务端。(可选)
class TcpServer
{
publicstatic void main(String[] args) throws Exception
{
//建立服务端的Socket服务,并监听一个端口。
ServerSocketss = new ServerSocket(10004);
//通过accept方法获取连接过来的客户端对象。
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();//关闭客户端。
ss.close();//可选
}
}
服务端
这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程。
这是B客户端连接,只有等待。
因为服务端还没有处理完A客户端的请求,还循环回来执行下次accept方法。所以暂时获取不到B客户端对象。
那么为了可以让多个客户端同时并发访问服务端。
那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。
如何定义线程呢?
只要明确了每一个客户端要在服务端执行的代码,将该代码存入run方法中。
自定义浏览器——Tomcat服务端图例:
URL对象
URL常用方法:
String getFile():获取此URL的文件名。
String getHost():获取此URL的主机名(如果适用)。
String getPath():获取此URl的路径部分。
int getPort():获取此URL的端口号。
String getProtocol():获取此URL的协议名称。
String getQuery():获取此URl的查询部分。
会出现这个异常:MalformedURLException
装包拆包图例:
URLConnection必须掌握。
import java.io.*;
import java.net.*;
class URLConnectionDemo
{
publicstatic void main(String[] args) throws Exception
{
URLurl = newURL(http://192.168.1.102/myweb/demo.html?name=haha&&age=10);
URLConnectionconn = url.openConnection();
System.out.println(conn);
InputStreamin = conn.getInputStream();
byte[]buf = new byte[1024];
intlen = in.read(buf);
System.out.println(newString(buf,0,len));
}
}
域名解析:
想要将主机名翻译成IP地址,需要域名解析DNS。
域名解析图例: