您的位置:首页 > 理论基础 > 计算机网络

黑马程序员 网络编程

2015-08-29 10:21 585 查看
------- android培训java培训、期待与您交流! ----------

网络编程

Java中的.net包提供了网络通信的类和服务。

1.网络模型:OSI参考模型和TCP/IP参考模型。

一般来说开发处于传输层和网际层。应用层为:FTP和HTTP协议等。传输层为:UDP和TCP等。网际层为:IP。

通常用户操作的是应用层,而编程人员需要做的是传输层和网际层,用户在应用层操作的数据,经过逐层封包,最后到物理层发送到另一个模型中,再进行逐层解包,最后回到应用层

2.网络通信的要素

找到对方IP
数据要发送到指定的应用网络上,为了标识这些程序,故给这些网络应用程序都使用数字进行标识。为了方便称呼其为端口,逻辑端口
定义通信规则。这个通信规则被称为协议,国际网络通信通用协议TCP/IP。

IP地址在Java中对应的对象是InetAddress。它有几个重要的方法:

static InetAddress getByName(String host):获取指定主机的IP和主机名。这个方法是静态的,注意到这个类不能直接new对象,只能通过其本身的静态方法得到
本类对象。
String getHostAddress():返回IP地址字符串文本形式。
String getHostName():返回IP地址主机名。
public static InetAddress getLocalHost():返回本地主机。

一个获取指定主机的例子

import java.net.*;
class getIP
{
public static void main(String[] args)throws Exception
{
//获取本机的Address对象
InetAddress ia=InetAddress.getLocalHost();

//打印本机的名字及地址
String name=ia.getHostName();
String address=ia.getHostAddress();
System.out.println(name+" "+address);

//获取指定主机的ip信息
InetAddress i=InetAddress.getByName("127.0.0.1");
String na=i.getHostName();
String add=i.getHostAddress();
System.out.println(name+" "+address);
//当获取的主机返回的对象不唯一时可以使用InetAddress.getAllByName方法,返回的是一个InetAddress数组

}
}


3.TCP与UDP

UDP:

不需要建立连接,将数据和源封装在数据包中。
每个数据包的大小限制在64k以内,数据超过64k将自动拆分。
面向无连接,所以是不可靠协议。
因为不需要连接,所以速度快

TCP:

需要建立连接,形成数据传输的通道。
可以在数据连接中进行大数据量的传输。
通过三次握手完成连接,是可靠的协议。
必须建立连接,效率稍低。

三次握手:第一次本方发送请求,第二次对方确认连接,第三次本方再次确认连接成功。

无论是UDP还是TCP连接,其使用的基类都是Socket类。

4.Socket

Socket是实现两台主机网络通信的端点,使用Socket类及其方法可以轻松完成网络通信的任务。

Socket的常用构造方法:

public Socket(InetAddress address,int port):创建一个Socket对象并将其连接到指定 IP 地址的指定端口号。
public Socket(String host,int port):也可以直接给出指定IP和端口来创建Socket对象。

Socket常用方法:

public InetAddress getInetAddress():返回包含该Socket对象连接主机的InetAddress对象。
public InputStream getInputStream():返回该Socket对象的输入流,一般用于TCP传输。
public OutputStream getOutputStream():返回该Socket对象的输出流,一般用于TCP传输。
public boolean isConnected():测试是否连接成功,连接成功则返回true。

5.UDP通信

Socket有一个可实现子类DatagramSocket用于给UDP通信。

DatagramSocket常用方法:

public void connect(InetAddress address,int port):连接到指定地址和端口。当连接到远程地址时,包就只能从该地址发送或接收。
public boolean isConnected():返回连接状态,若已连接则返回true。
public void send(DatagramPacket p):发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
public void receive(DatagramPacket p):接收数据报包。返回的信息会覆盖掉原DatagramPacket的内容。
DatagramPacket数据报包,这个包包含了将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。

DatagramPacket构造方法有:

public DatagramPacket(byte[] buf,int length):构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket(byte[] buf, int length, InetAddress address, int port) :构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

DatagramPacket常用方法有:

public InetAddress getAddress():返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
public int getPort():返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
public byte[] getData():返回数据缓冲区。
public int getLength():返回将要发送或接收到的数据的长度。
public void setAddress(InetAddress iaddr):设置要将此数据报发往的那台机器的 IP 地址。
public void setPort(int iport):设置要将此数据报发往的远程主机上的端口号。
public void setData(byte[] buf):为此包设置数据缓冲区。

使用Udp进行通信时:

建立两个DatagramSocket,接收端的Socket必须制定一个端口。
建立数据包,将数据和接收端的地址和端口都封装进去
调用发送端Socket的send方法,将数据包发送出去
接收端,通过receive方法接收数据包
关闭资源

发送端:

class ChatSend
{
private DatagramSocket ds;

ChatSend()
{
try
{
ds = new DatagramSocket();
}
catch (SocketException e)
{
System.out.println("未建立连接服务");
return;
}
}
public void chat()
{

try
{
byte[] buf = "这是一个小程序".getBytes();
ds.send(new DatagramPacket(buf,buf.length,
InetAddress.getByName("127.0.0.1"),10010));
//将要发送的数据转成数组后打包成DatagramPacket并发送出去
ds.close();

}
catch (IOException e)
{
e.printStackTrace();
}

}

}


接收端:

class ChatReceive
{
private DatagramSocket ds;

ChatReceive()
{
try
{
ds = new DatagramSocket(10000);
}
catch (SocketException e)
{
System.out.println("未建立连接服务");
return;
}
}
public void chat()
{
try
{
byte[] by = new byte[1024*64];
DatagramPacket dp = new DatagramPacket(by,by.length);
//新建一个空包用来存放数据
ds.receive(dp);
//结束数据并存放在空包内
String ip = dp.getAddress().getHostAddress();
int port  = dp.getPort();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port+" "+data);
//获取包内信息
ds.close();
}
catch (IOException e)
{
e.printStackTrace();
}

}

}


6.TCP通信

TCP通信要用到专门的服务端ServerSocket。这个类主要用来接收Socket对象。

ServerSocket构造方法有:

public ServerSocket(int port):创建绑定到特定端口的SeverSocket对象。

ServerSocket常用方法有:

public Socket accept():从监听端口接收发送过来的Socket对象。
public int getLocalPort():返回监听的端口地址。

使用TCP通信的一般步骤:

服务端:

建立服务端的Socket服务,并监听一个端口;(SeverSocket)
获取连接过来的客户端对象,通过SeverSocket的accept方法。该方法为阻塞式方法;
.客户端如果发送数据,那么服务端就要使用对应的对象,并且使用客户端的对象的读取流来获得数据
关闭客户端。
.关闭服务端(可选)。

class ChatRece
{
private ServerSocket ss= null;
ChatRece()
{
try
{
ss = new ServerSocket(10086);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void chat()
{

while(true)
{
try
{
Socket s = ss.accept();
new Thread(new ChatServerThread(s)).start();
//每接受一个服务端就新建一个通信。
}
catch (IOException e)
{
System.out.println("建立连接失败");
continue;
}
}
}
}

class ChatServerThread implements Runnable
{
private Socket s;
ChatServerThread(Socket s)
{
this.s = s;
InetAddress ia = s.getInetAddress();
String address = ia.getHostAddress();
System.out.println(address+"已建立连接");//获得客户端的ip信息
}
public void run()
{
try
{
//读取数据,经过获得的Socket对象的读取流读出数据
BufferedReader bfr = new BufferedReader(new InputStreamReader(s.getInputStream()));

String data = null;
while((data = bfr.readLine())!=null)
{
System.out.println(data);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}


客户端

建立客户端的Socket服务,指定主机和一个端口;
为了发送数据要获得Socket中的输入输出流。
使用客户端的write方法就可以向服务端发送数据了
关闭客户端。

class ChatSe
{
private Socket s= null;
private InetAddress ia =null;
ChatSe(String adress,int port)
{
try
{
ia = InetAddress.getByName(adress);
s = new Socket(ia,port);//建立指定端口的Socket服务
System.out.println("建立连接成功");
}
catch (Exception e)
{
System.out.println("建立连接失败");
return;
}
}
public void chat()
{
try
{
BufferedWriter bfw = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
BufferedReader bfr = new BufferedReader(
new InputStreamReader(System.in));
//信息从键盘输入并传给服务端
String data = null;
while((data = bfr.readLine())!=null)
{
if(data.equals("over"))//设定信息结束标记
break;
bfw.write(data);
bfw.newLine();//必要的,由于readline是不读取/r/n的如果不加这句,
//在服务端就读取不到/r/n,读取就不能结束
bfw.flush();
}
s.shutdownOutput();//关闭客户端的输出流。相当于给流中加入一个结束标记-1.

bfr.close();
s.close();
}
catch(IOException e)
{
System.out.println("发送数据失败");
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: