一.概述
实现不同主机上的数据通信,而要实现通讯则需要首先知道对方的IP和端口号,同时明确双方使用的通信规则,或传输协议IP地址:主机在网络的地址,或者在网上的唯一标识 端口号:数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识,为了方便称呼这个数字,就这个数组叫为“端口”,或“逻辑端口”,它并没有物理实体与之对应。有效端口好从0~65535,其中0~1024是系统保留的。一些常用程序的默认端口:浏览器80端口,TomCat服务器8080端口,MySQL的3306端口 传输协议:即传输协议,国际组织定义的通用协议是TCP/IP。TCP/IP既能用于局域网,也能用于广域网。除了TCP/IP,还有其他的协议,例如UDP、FTP、HTTP等 TCP和UDP在传输层。IP协议在网络层。FTP协议、HTTP协议在应用层
数据封包: 数据拆包: IP地址:
体系结构:
|----InetAddress
|----Inet4Address,
|----Inet6Address
InetAddress中没有提供构造函数,但它提供了多种静态方法,以获取本类对象
socket地址:封装的是带端口号的IP地址
|——SocketAddress
|———InetSocketAddress
eg:import java.net.*;
class IPDemo
{
public static void main(String[] args) throws Exception
{
/*
* //下边这句话会报未知主机异常
* //获取本地主机IP地址
InetAddress i= InetAddress.getLocalHost();
System.out.println(i.toString());
String adr = i.getHostAddress();
String name = i.getHostName();
sop("adr="+adr+" name="+name);
*/
//获取其他主机IP地址
//通过主机名获取IP地址,需要解析,所以较慢,而且对于百度、新浪这样的主机名,获得的IP地址可能不唯一。
InetAddress i= InetAddress.getByName("www.sina.com");
System.out.println(i.toString());
String adr = i.getHostAddress();//获得IP地址的字符串表现形式
String name = i.getHostName();//获取主机名
sop("adr="+adr+" name="+name);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
二.TCP与UDP 区别
UDP:是面向无连接的,它将数据集源和目的封装成数据包中,不需要建立连接;它的每个数据报(Datagram)的大小限制在64k以内;因为无连接,是不可靠的协议;同样因为不需要建立里连接,所以速度快。
应用特点:只求速度快,数据丢失对程序影响不大。
应用程序实例:聊天室工具、视频、网络会议等
TCP:
需要建立连接,形成传输数据的通道;在连接中进行大量数据传输;通过三次握手协议完成连接,是可靠的协议;因为必须建立连接,所以效率会稍低。(TCP不像UDP需要封包,而且每个包不能超过64k,它可以大量的传输数据)。
应用特点:适合对数据完整性要求高的程序。
应用程序实例:下载程序
SOCKET:
网络编程其实就Socket编程,Socket是为网络服务的一种机制。(Socket,中文意思为插座)
通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输
UDP传输:
UDP两端是发送端和接受端
DatagramSocket:UDP传输专用的程序通信端点,既能发送也能接受
DatagramSocket:数据报包,封装了UDP传输的数据报。里边可以设置要发送的目的地IP地址、端口及要发送的数据
eg:
/*
需求:通过Udp传输方式,将一段文字数据发送出去。
定义一个udp发送端。
思路:
1。建立UDPsocket服务。
2.提供数据,并将数据封装到数据包中。
3.通过socket服务的发送功能,将数据包发出去。
4.关闭资源。
*/
class UdpSend
{
public static void main(String[] args) throws Exception
{
//1.创建UDP服务,通过DatagramSocket对象。
DatagramSocket ds = new DatagramSocket(8888);
//2.确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port)
byte[] buf = "UDP i coming!".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.13"),10000);
//3.通过socket服务,将已有的数据包发送出去,通过send方法。
ds.send(dp);
//4.关闭资源。它使用了底层的资源,所以要关闭资源。
ds.close();
}
}
/*
需求;
定义一个应用程序,用于接收并处理数据。
定义udp接受端
思路:
1.定义socket服务,通常会监听一个端口,其实就是给这个接受网络应用程序定义一个数字标示。
方便与明确哪些数据过来该应用程序可以处理。
2.定义一个数据包,因为要存储要接受到的字节数据,
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3.通过socket服务的receive方法将收到的数据存入已定义的数据包中。
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。
5.关闭资源。
*/
class UdpRece
{
public static void main(String[] args) throws Exception
{
//1.创建udpsocket,建立端点。这里必须定义监听的端口,其实就是给网络应用程序定义数字标识。
DatagramSocket ds = new DatagramSocket(10000);
//2.定义数据包,用于存储数据。
byte [] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3.通过服务的receive方法,将收到的数据存入到数据包中。
ds.receive(dp);//receive是一个阻塞式方法没有接受到数据,会一直等待
//4.获取数据包中的方法获取其中的数据。
InetAddress i= dp.getAddress();
String ip = i.getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
int port = dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
//5、关闭资源
ds.close();
}
}
eg:
import java.io.*;
class UdpSend2
{
public static void main(String[] args) throws Exception
{
DatagramSocket dg = new DatagramSocket(18000);
//读取键盘录入
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
String line = null;
//192.168.1.255是这个网段的广播地址,用它就能实现局域网群聊。
InetAddress ip = InetAddress.getByName("192.168.1.255");
DatagramPacket dp = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
byte [] buf = ("sender:"+line).getBytes();
dp = new DatagramPacket(buf,0,buf.length,ip,17000);
dg.send(dp);
}
dg.close();
}
}
class UdpRece2
{
public static void main(String[] args) throws Exception
{
DatagramSocket dg = new DatagramSocket(17000);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
while(true)
{
dg.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println("("+ip+":"+dp.getPort()+")"+data);
//System.out.println(new String(buf,0,dp.getLength()));
}
}
}
UDP 聊天程序
eg:
/*
编写一个聊天程序
有接受数据的部分,和发数据的部分。
这两部分需要同时执行。那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法,
而且run方法要封装到不同的类中。
*/
import java.net.*;
import java.io.*;
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();
//把发送地址,设为广播地址,
InetAddress i = InetAddress.getByName("192.168.1.255");
DatagramPacket dp=
new DatagramPacket(buf,0,buf.length,i,10020);
ds.send(dp);
}
ds.close();
}
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:"+ip+" data:"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接受端失败");
}
}
}
class ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSoket = new DatagramSocket();
DatagramSocket receSoket = new DatagramSocket(10020);
new Thread(new Send(sendSoket)).start();
new Thread(new Rece(receSoket)).start();
}
}
------- android培训、java培训、期待与您交流! ----------