黑马程序员_java之网络编程

网络编程

网络通讯三要素:IP地址、端口号、传输协议

特殊IP地址:127.0.0.1本地回环地址,对应的主机名为 localhost,可用来测试网卡ping 127.0.0.1;192.168常用保留地址段,IPV4 、IPV6(可以数字和字母)

端口号:标示进程的逻辑地址,有效端口为0-65535,其中0-1024为系统使用或保留端口;常见端口:

            Web端口80 Tomact端口8080 MySql 3306

协议:常见协议TCP/IP、UDP, 例:特有机构有专门的协议

网络模型:OSI参考模型,TCP/IP参考模型

OSI参考模型:应用层(数据+应用层特征)、表示层、会话层、传输层(+TCP/UDP信息)、网络层(+IP信息)、数据链路层(+传输方式、底层协议)、物理层(物理层设备如网线、光纤、无线(红外))

TCP/IP参考模型:应用层、传输层、网际层、主机至网络层

TCP传输控制协议、UDP用户数据报协议、FTP/HTTP 应用层协议

Web开发在应用层、网络编程在传输层、网际层

两台电脑通讯:先不断数据封包、再不断数据拆包。

获取IP信息:通过java.net包中的InetAddress

例子:InetAddress ia=InetAddress.getLocalHost();//获取主机名,本地IP信息

InetAddress ia2=InetAddress.getByName (“”);//获取任一台主机信息

//若IP地址和主机名映射关系没在网络上。能找到IP地址,解析不成功,名字还是IP地址

Ia.getHostAddress();//获取IP地址

Ia.getHostName();//获取主机名

TCP和UDP区别:

UDP:将数据及源和目的封装成数据包中,不需建立连接

          每个数据包大小限制在64K内

          因无连接,是不可靠协议,易丢包

          因不需建立连接,速度快

常见应用:聊天、网络视频、桌面共享

TCP:建立连接,形成传输数据的通道

          在连接中进行大数据量传输

          通过三次握手完成连接,可靠

          面向连接、效率稍低

Socket:为网络服务提供的一种机制

通信的两端都有Socket

网络通信其实就是Socket间的通信

数据在两个Socket之间通过IO传输

Socket相当于码头中的港口,每个应用程序都有类似的插座

UDP发送接收数据:

DatagramSocket 发送接收数据包套接字 DatagramPacket无连接包投递服务

发送端发送数据步骤:1、建立发送端服务

                                      2、提供数据包并打包

                                      3、通过socket服务发送

                                      4、关闭资源

接收端接收数据步骤:1、建立接收端服务,通常监听一端口

                                      2、定义数据包存储接收数据

                                      3、通过socket服务接收数据存入定义的数据包中

                                      4、通过数据包对象取出数据

                                      5、关闭资源

/需求:通过udp传输方式,将一段文字数据发出去

 class UdpSend {

    public static void main(String[] args)throws Exception  {

       DatagramSocket ds=new DatagramSocket();

       byte [] buf="udp ge men lai le".getBytes();

       DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.112.87"),10000);

       ds.send(dp);

       ds.close();

    }

}

 //定义一个应用程序。用于接收udp协议传输的数据并处理

 class UdpRece {

    public static void main(String[] args)throws Exception  {

       DatagramSocket ds=new DatagramSocket(10001);

       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());

       int port=dp.getPort();

       System.out.println(ip+"::"+data+"::"+port);

       ds.close();

    }

}

Udp键盘录入数据:接收端用while(true),不会死循环,有阻塞式方法;去掉关闭资源语句

编写一个聊天程序

TCP发送接收数据:

客户端Socket 服务端ServerSocket

客户端发送数据步骤:1、建立Socket服务,并指定要连接的主机名和端口

                                      2、获取Socket流中的输出流                              

                                      3、关闭资源

接收端接收数据步骤:1、建立Socket服务,通过ServerSocket,通常监听一端口

                                      2、获取连接过来的Socket对象,通过accept方法(阻塞式)

                                      3、获取socket对象的读取流

                                       4、关闭资源(关闭客服端;而关闭服务端可选)

//给服务端发送一个文本数据

class TcpClinet {

    public static void main(String[] args) throws Exception {

       Socket s=new Socket("169.254.112.87",10005);

       OutputStream out=s.getOutputStream();

       out.write("tcp ge men lai le".getBytes());

       s.close();

    }

}

//建立断点接收数据,并打印在控制台

class TcpServer{

    public static void main(String[] args)throws Exception  {

       ServerSocket ss=new ServerSocket(10005);

       Socket s=ss.accept();//阻塞式方法

       String ip=s.getInetAddress().getHostAddress();

       System.out.println(ip+"....connected");

       InputStream in=s.getInputStream();//源是网络流

       byte [] buf=new byte[1024];

       int len=in.read(buf);

       System.out.println(new String(buf,0,len));

       s.close();

       ss.close();//可选

    }

}

演示:Tcp传输的客户端和服务端互访

客户端发完后就会等因为read是阻塞式方法

TCP练习:服务端客户端容易两边挂起,如TCP复制文件,服务端反馈上传成功,因为服务端客户端都用到readline方法,而此方法是阻塞式方法,

如果不加结束标记的话,两端都会莫名的等待。有两种解决方式一种是加时间戳另外一种是Socket对象的shutdownOutput方法。

import java.io.*;

import java.net.*;

class TextClinet {

    public static void main(String[] args) throws Exception {

       Socket s=new Socket("169.254.112.87",10008);

       BufferedReader bufr=

           new BufferedReader(new FileReader("IPDemo.java"));

       PrintWriter out=new PrintWriter(s.getOutputStream(),true);

       //时间戳

       /*DataOutputStream dos=new DataOutputStream(s.getOutputStream());

       long time=System.currentTimeMillis();

       dos.writeLong(time);*/

       String line=null;

       while((line=bufr.readLine())!=null){

           out.println(line);

       }

       //dos.writeLong(time);

       //关闭客户端输出流,相当于给流结束标记-1

       s.shutdownOutput();

       BufferedReader bufIn=

           new BufferedReader(new InputStreamReader(s.getInputStream()));

       String str=bufIn.readLine();

       System.out.println("server:"+str);

       bufr.close();

       s.close();

    }

}

class TextServer{

    public static void main(String[] args) throws Exception {

       ServerSocket ss=new ServerSocket(10008);

       Socket s=ss.accept();

       String ip=s.getInetAddress().getHostAddress();

       System.out.println(ip+"....connected");

       //时间戳

       /*DataInputStream dis=new DataInputStream(s.getInputStream());

       long l=dis.readLong();*/

       BufferedReader bufIn=

           new BufferedReader(new InputStreamReader(s.getInputStream()));

       //文件名字写死了

       PrintWriter out=new PrintWriter(new FileWriter("server.txt"),true);

       String line=null;

       while((line=bufIn.readLine())!=null){

           //判断时间戳

           out.println(line); //读到了,但是没结束标记,就会等 

       }

       PrintWriter pw=new PrintWriter(s.getOutputStream(),true);

       pw.println("上传成功");

       out.close();

       s.close();

       ss.close();

    }

}

URL对象(统一资源定位符):URI范围比URI大

String getHost() 返回此 URI 的主机组成部分。

String getPath() 返回此 URI 的已解码的路径组成部分。

int getPort()   返回此 URI 的端口号。

String getQuery()  返回此 URI 的已解码的查询组成部分。

String  getProtocol() 获取协议名称

String   getFile()  获取文件名

注:int port=url.getPort();if(port==-1;port=80;

例URL url=new URL(“”);

URLConnection conn=url.openConnection();//内部封装了Socket对象

InputStream in=conn.getInputStream();

Byte [] buf =new byte[1024];

Int len=0;

While((len=in.read(buf))!=-1){

         Sop(new string(buf,0,len));

}

注:Socket()构造函数void connect(SocketAddress endpoint)  将此套接字连接到服务器。SocketAddress抽象类有子类InetSocketAddress封装的是IP 地址 + 端口号

ServerSocket(int port, int backlog),backlog队列的最大长度,能连接到服务器的最多客服端个数

posted on 2013-01-28 16:28  念满  阅读(186)  评论(0编辑  收藏  举报