------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一 网络编程的定义
通过使用套接字来达到进程间的通信就是网络编程。也就是两个设备之间的数据交换,主要是指计算机之间的数据交换。目前网络编程都是基于请求/响应方式的。也就是一个设备发送请求给另外一个设备,并接收其反馈的信息。在网络编程中,发送请求的程序被称为客户端(Client),等待其他程序连接的程序成为服务器(Server)。
1,网络模型
OSI模型和TCP/IP模型:
2,网络通讯的三个要素:
IP地址,端口号,传输协议。
3,熟记的知识
主机名:localhost 本地回环地址:127.0.0.1
端口号:逻辑端口:用于标识进程的逻辑地址,不同进程的标识。有效端口:0~65535,其中0~1024系统使用或保留端口。
二 两种传输协议:
就是通讯的规则:TCP UDP
UDP:
1,将数据以及源和目的封装在数据报包中,不需要连接。
2,每个数据包的大小限制在64K内。
3,因为无连接,是不可靠协议。
4,因为不需要连接,所以速度较快。
TCP:
1,建立连接,形成传输数据的通道。
2,在连接中进行大数据量传输。
3,通过三次握手完成连接是可靠协议。
4,因为必须建立连接,所以效率稍低。
二者区别:
在使用中,类似于图像、声音等对可靠性要求没有那么高的业务可以用UDP,他们不需要准确存储,对准确性无要求,但要求速度快。
类似于文本、程序、文件等要求可靠的数据最好就用TCP,但会牺牲一些速度。
对系统资源的要求:TCP较多,UDP少。
程序结构:UDP程序结构较简单,TCP复杂。
流模式与数据报模式:TCP保证数据正确性,UDP可能丢包; TCP保证数据顺序,UDP不保证。
三 Java中的IP对象InetAddress和套接字Socket
1,InetAddress
InetAddress:不能直接创建对象,因为构造方法私有。
InetAddress InetAddress.getByName(String host);//通过给定的主机名获取Ip对象。
InetAddress getLocalHost();//返回本地主机IP对象。
ip.getHostAddress();//获取IP地址。
ip.getHostName();//获取主机名。
Example:
import java.net.*;
class InetDemo
{
public static void main(String[] args)throws UnknownHostException
{
InetAddress ip=InetAddress.getByName("liupeng-pc");//通过给定的主机名获取Ip对象。
System.out.println(ip.getHostAddress());//获取ip地址。
System.out.println(ip.getHostName());//获取主机名。
InetAddress ip1=InetAddress.getLocalHost();//获取本地主机ip对象。
System.out.println(ip1.getHostAddress());
System.out.println(ip1.getHostName());
}
}
2,Socket
Socket:套接字,通讯的端点。
就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket之 间的通信,数据在两个Socket间通过IO传输。
四 UDP传输
1,只要是网络传输,必须要有Socket。
2,数据一定要封装到数据包中,数据包中包括数据,目的地址,端口等信息。
直接操作UDP不可能,对于Java语言而言应将UDP封装成对象,易于我们的使用。这个对象就是DatagramSocket,封装了UDP传输协议的Socket对象。
因为数据包中包含的信息较多,为了操作这些信息方便,也一样会将其封装成对象。这个数据包对象就是:DatagramPacket.通过这个对象中的方法,就可以获取到数据包中的各种信息。
DatagramSocket具备发送和接受功能,在进行udp传输时,需要明确一个是发送端,一个是接收端。
UDP的发送端步骤:
1,建立UDP的Socket服务,创建对象时如果没有指定端口,系统会自动分配一个未被使用的端口。
2,明确要发送的具体数据。
3,将数据封装成了数据包。
4,用Socket服务的Send方法将数据包发送出去。
5,关闭资源。
UDP的接收端步骤:
1,创建udp的socket服务,必须要明确一个端口,作用在于,只有发送到这个端口的数据才是这个接收端可以处理的数据。
2,定义数据包,用于存储接收到数据。
3,通过socket服务的接收方法将收到的数据存储到数据包中。
4,通过数据包的方法获取数据包中的具体数据内容,比如ip、端口、数据等等。
5,关闭资源。
Example:
import java.net.*;
//UDP发送端:
class UdpSend
{
public static void main(String []args)throws Exception
{
//1,创建UDPdseSocket服务。
DatagramSocket ds=new DatagramSocket();
//2,明确要发送的具体数据。
String str="haha";
byte[] buf=str.getBytes();
//3,将数据封装成数据包。
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("liupeng-pc"),10000);
//4,用Socket服务的Send将数据发送出去。
ds.send(dp);
//5,关闭资源。
ds.close();
}
}
//UDP接收端:
class UdpReceive
{
public static void main(String []args)throws Exception
{
//1,创建UDPdevSocket服务。
DatagramSocket ds=new DatagramSocket(10000);
//2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//3,通过socket服务的接收方法将收到的数据存储到数据包中。
ds.receive(dp);
//3,通过socket服务的接收方法将收到的数据存储到数据包中。
String ip=dp.getAddress().getHostAddress();
int port=dp.getPort();
String str=new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port+":"+str);
//5,关闭资源。
ds.close();
}
}
Example:
//UDP聊天:
import java.net.*;
import java.io.*;
class UdpDemo2
{
public static void main(String[] args)throws Exception
{
DatagramSocket ds=new DatagramSocket();
DatagramSocket ds1=new DatagramSocket(10005);
new Thread(new UdpSend(ds)).start();
new Thread(new UdpReceive(ds1)).start();
}
}
class UdpSend implements Runnable
{
private DatagramSocket ds;
public UdpSend(DatagramSocket ds)
{
super();
this.ds=ds;
}
public void run()
{
try{
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bufr.readLine())!=null)
{
byte[] buf=line.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("liupeng-pc"),10005);
ds.send(dp);
}
ds.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
class UdpReceive implements Runnable
{
private DatagramSocket ds;
public UdpReceive(DatagramSocket ds)
{
super();
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 str=new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+str);
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
五 Tcp传输
TCP传输:两个端点的建立连接后会有一个传输数据的通道,这通道称为流,而且是建立在网络基础上的流,称之为socket流。该流中既有读取,也有写入。
tcp的两个端点:一个是客户端,一个是服务端。
客户端:对应的对象,Socket
服务端:对应的对象,ServerSocket
TCP客户端:
1,建立tcp的socket服务,最好明确具体的地址和端口。这个对象在创建时,就已经可以对指定ip和端口进行连接(三次握手)。
2,如果连接成功,就意味着通道建立了,socket流就已经产生了。只要获取到socket流中的读取流和写入流即可,只要通过getInputStream和getOutputStream就可以获取两个流对象。
3,关闭资源。
Example:
//TCP客户端:
Class TcpClient
{
public static void main(String[]args)
{
//创建Socket对象
Socket s=new Socket(“127.0.0.1”,10000);
//获取写入流。
OutputStream os=s.getOutputStream();
//写入数据
os.write(“我来了”.getBytes());
关闭流
S.close();
}
}
Example:
//TCP服务端:
1,创建服务端socket服务,并监听一个端口。
2,服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象。
3,可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。
4,如果通讯结束,关闭资源。注意:要先关客户端,再关服务端。
class TcpServer{
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(10002);//建立服务端的socket服务
Socket s = ss.accept();//获取客户端对象
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");
// 可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。
InputStream in = s.getInputStream();//读取客户端的数据,使用客户端对象的socket读取流
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf,0,len);
System.out.println(text);
// 如果通讯结束,关闭资源。注意:要先关客户端,在关服务端。
s.close();
ss.close();
}
}