Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

黑马程序员-java基础学习网络编程1

$
0
0

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ---------


网络通讯要素
    IP地址
    端口号
    传输协议
IP地址
网络中设备的标识
不易记忆,可用主机名
本地回环地址:127.0.0.1 主机名:localhost


InetAddress类(java.net包)
  1)此类表示互联网协议 (IP) 地址。
  IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,
  UDP 和 TCP 协议都是在它的基础上构建的
  InetAddress 的实例包含 IP 地址,还可能包含相应的主机名
  (取决于它是否用主机名构造或者是否已执行反向主机名解析)。 
  2)方法摘要 
  boolean equals(Object obj) 
     将此对象与指定对象比较。 
  byte[] getAddress() 
     返回此 InetAddress 对象的原始 IP 地址。 
  static InetAddress getByName(String host) 
     在给定主机名的情况下确定主机的 IP 地址。 
  String getHostAddress() 
     返回 IP 地址字符串(以文本表现形式)。 
  String getHostName() 
     获取此 IP 地址的主机名。 
  static InetAddress getLocalHost() 
     返回本地主机。 
  String toString() 
     将此 IP 地址转换为 String。
  static InetAddress getLocalHost() 
     返回本地主机。
  static InetAddress[] getAllByName(String host) 
     在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
     

端口号
用于表示进程的逻辑地址,不同进程的标识
有效端口:0到65535,其中0到1024系统使用或保留端口


传输协议
通讯的规则
常见协议:TCP,UDP

UDP
将数据及源和目的封装成数据包中,不需要建立连接
每个数据包的大小限制在64K内
因无连接,是不可靠协议
不需要建立连接,速度快


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

Socket
Socket就是为网络服务提供的一种机制
通信两端都有Socket
网络通信其实就是Socket间的通信
数据在两个Socket间通过IO传输


DatagramSocket类(java.net包)
  1)此类表示用来发送和接收数据报包的套接字。
  数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。
  从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。


  在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。
  在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。
  2)构造方法摘要 
  DatagramSocket() 
     构造数据报套接字并将其绑定到本地主机上任何可用的端口。 
  protected  DatagramSocket(DatagramSocketImpl impl) 
     创建带有指定 DatagramSocketImpl 的未绑定数据报套接字。 
  DatagramSocket(int port) 
     创建数据报套接字并将其绑定到本地主机上的指定端口。 
  DatagramSocket(int port, InetAddress laddr) 
     创建数据报套接字,将其绑定到指定的本地地址。 
  DatagramSocket(SocketAddress bindaddr) 
     创建数据报套接字,将其绑定到指定的本地套接字地址。 
  3)方法摘要 
  void receive(DatagramPacket p) 
     从此套接字接收数据报包。 
  void send(DatagramPacket p) 
     从此套接字发送数据报包。 
  void close() 
     关闭此数据报套接字。 
  void connect(InetAddress address, int port) 
     将套接字连接到此套接字的远程地址。 
  
 3.类 DatagramPacket(java.net包)


  1)此类表示数据报包
  2)构造方法摘要 
  DatagramPacket(byte[] buf, int length) 
     构造 DatagramPacket,用来接收长度为 length 的数据包。 
  DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
     构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。 
  3)方法摘要 
  InetAddress getAddress() 
     返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。 
  byte[] getData() 
     返回数据缓冲区。 
  void setData(byte[] buf) 
     为此包设置数据缓冲区。
  void setLength(int length) 
     为此包设置长度。 
  void setPort(int iport) 
     设置要将此数据报发往的远程主机上的端口号。 
  int getLength() 
     返回将要发送或接收到的数据的长度。 
  int getPort() 
     返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。


练习
import java.net.*;


/*
需求:通过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 ge men lai le ".getBytes();
DatagramPacket dp = 
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),10000);

//3,通过socket服务,将已有的数据包发送出去。通过send方法。
ds.send(dp);

//4,关闭资源。
ds.close();
}
}
/*
需求:
定义一个应用程序,用于接收udp协议传输的数据并处理的。

定义udp的接收端。
思路:
1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识。
方便于明确哪些数据过来该应用程序可以处理。


2,定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
5,关闭资源。


*/

class  UdpRece
{
public static void main(String[] args) throws Exception
{
//1,创建udp socket,建立端点。
DatagramSocket ds = new DatagramSocket(10000);
while(true)
{
//2,定义数据包。用于存储数据。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);


//3,通过服务的receive方法将收到数据存入数据包中。
ds.receive(dp);//阻塞式方法。



//4,通过数据包的方法获取其中的数据。
String ip = dp.getAddress().getHostAddress();


String data = new String(dp.getData(),0,dp.getLength());


int port = dp.getPort();


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


}
//5,关闭资源
//ds.close();


}
}

键盘录入练习
import java.net.*;
import java.io.*;
class  UdpSend2
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket();


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


DatagramPacket dp = 
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10001);


ds.send(dp);
}
ds.close();
}
}

class  UdpRece2
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket(10001);


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+"::"+data);
}
}
}

/*
编写一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。


因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。


*/
import java.io.*;
import java.net.*;
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)
{

byte[] buf = line.getBytes();

DatagramPacket dp = 
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10002);


ds.send(dp);


if("886".equals(line))
break;
}
}
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());

if("886".equals(data))
{
System.out.println(ip+"....离开聊天室");
break;
}
System.out.println(ip+":"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}

class  ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10002);


new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}

TCP传输
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭Socket

同样,客户端与服务端是两个独立的应用程序
类 Socket(java.net )

  1)此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点
  2)构造方法摘要 
  Socket() 
     通过系统默认类型的 SocketImpl 创建未连接套接字 
  Socket(InetAddress address, int port) 
     创建一个流套接字并将其连接到指定 IP 地址的指定端口号。 
  Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 
     创建一个套接字并将其连接到指定远程地址上的指定远程端口。
  Socket(String host, int port) 
     创建一个流套接字并将其连接到指定主机上的指定端口号。
  Socket(String host, int port, InetAddress localAddr, int localPort) 
     创建一个套接字并将其连接到指定远程主机上的指定远程端口。 
  3)方法摘要 
  void bind(SocketAddress bindpoint) 
     将套接字绑定到本地地址。 
  void close() 
     关闭此套接字。 
  void connect(SocketAddress endpoint) 
     将此套接字连接到服务器。 
  void connect(SocketAddress endpoint, int timeout) 
     将此套接字连接到服务器,并指定一个超时值。 
  InetAddress getInetAddress() 
     返回套接字连接的地址。 
  InputStream getInputStream() 
     返回此套接字的输入流。 
  OutputStream getOutputStream() 
     返回此套接字的输出流。 
  int getPort() 
     返回此套接字连接到的远程端口。 
  String toString() 
     将此套接字转换为 String。 
  
 3.类 ServerSocket(java.net)


  1)此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
  2)构造方法摘要 
  ServerSocket() 
     创建非绑定服务器套接字。 
  ServerSocket(int port) 
     创建绑定到特定端口的服务器套接字。 
  ServerSocket(int port, int backlog) 
     利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。 
  ServerSocket(int port, int backlog, InetAddress bindAddr) 
     使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。 
  3)方法摘要 
  Socket accept() 
     侦听并接受到此套接字的连接。 
  void close() 
     关闭此套接字。
  void bind(SocketAddress endpoint) 
     将 ServerSocket 绑定到特定地址(IP 地址和端口号)。 
  void bind(SocketAddress endpoint, int backlog) 
     将 ServerSocket 绑定到特定地址(IP 地址和端口号)。 
  String toString() 
     作为 String 返回此套接字的实现地址和实现端口。    
/*
演示tcp传输。

1,tcp分客户端和服务端。
2,客户端对应的对象是Socket。
服务端对应的对象是ServerSocket。
*/

/*
客户端,
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。
因为tcp是面向连接的。所以在建立socket服务时,
就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。


需求:给服务端发送给一个文本数据。


步骤:
1,创建Socket服务。并指定要连接的主机和端口。

*/
import java.io.*;
import java.net.*;
class  TcpClient
{
public static void main(String[] args) throws Exception 
{
//创建客户端的socket服务。指定目的主机和端口
Socket s = new Socket("192.168.1.254",10003);

//为了发送数据,应该获取socket流中的输出流。
OutputStream out = s.getOutputStream();


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




s.close();
}
}


/*
需求:定义端点接收数据并打印在控制台上。

服务端:
1,建立服务端的socket服务。ServerSocket();
并监听一个端口。
2,获取连接过来的客户端对象。
通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。
3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。
并打印在控制台。


4,关闭服务端。(可选)

*/
class  TcpServer
{
public static void main(String[] args) throws Exception
{
//建立服务端socket服务。并监听一个端口。
ServerSocket ss = new ServerSocket(10003);


//通过accept方法获取连接过来的客户端对象。
while(true)
{
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();
}
}


import java.io.*;
import java.net.*;
/*
演示tcp的传输的客户端和服务端的互访。


需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。


*/

/*
客户端:
1,建立socket服务。指定要连接主机和端口。
2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。
3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。
4,关闭客户端资源。

*/
class TcpClient2 
{
public static void main(String[] args)throws Exception 
{
Socket s = new Socket("192.168.1.254",10004);

OutputStream out = s.getOutputStream();


out.write("服务端,你好".getBytes());



InputStream in = s.getInputStream();


byte[] buf = new byte[1024];


int len = in.read(buf);


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


s.close();
}
}
class TcpServer2
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10004);


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

OutputStream out = s.getOutputStream();


Thread.sleep(10000);
out.write("哥们收到,你也好".getBytes());


s.close();


ss.close();
}
}


/*


需求:建立一个文本转换服务器。
客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。
而且客户度可以不断的进行文本转换。当客户端输入over时,转换结束。


分析:
客户端:
既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。
源:键盘录入。
目的:网络设备,网络输出流。
而且操作的是文本数据。可以选择字符流。


步骤
1,建立服务。
2,获取键盘录入。
3,将数据发给服务端。
4,后去服务端返回的大写数据。
5,结束,关资源。


都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。

*/
import java.io.*;
import java.net.*;


class  TransClient
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("192.168.1.254",10005);




//定义读取键盘数据的流对象。
BufferedReader bufr = 
new BufferedReader(new InputStreamReader(System.in));

//定义目的,将数据写入到socket输出流。发给服务端。
//BufferedWriter bufOut = 
//new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//打印流
PrintWriter out = new PrintWriter(s.getOutputStream(),true);


//定义一个socket读取流,读取服务端返回的大写信息。
BufferedReader bufIn = 
new BufferedReader(new InputStreamReader(s.getInputStream()));

String line = null;

while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;

out.println(line);//带换行
// bufOut.write(line);
// bufOut.newLine();
// bufOut.flush();

String str =bufIn.readLine();
System.out.println("server:"+str);

}


bufr.close();
s.close();

}
}
/*


服务端:
源:socket读取流。
目的:socket输出流。
都是文本,装饰。


*/


class  TransServer
{
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");


//读取socket读取流中的数据。
BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream()));


//目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。
//BufferedWriter bufOut = 
//new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//打印流
PrintWriter out = new PrintWriter(s.getOutputStream(),true);


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


System.out.println(line);


out.println(line.toUpperCase());//带换行
// bufOut.write(line.toUpperCase());
// bufOut.newLine();
// bufOut.flush();
}


s.close();
ss.close();


}
}
/*
该例子出现的问题。
现象:客户端和服务端都在莫名的等待。
为什么呢?
因为客户端和服务端都有阻塞式方法。这些方法么没有读到结束标记。那么就一直等
而导致两端,都在等待。




*/

作者:abcdwanglei 发表于2013-4-6 22:56:46 原文链接
阅读:130 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>