获取本地主机相关信息:
InetAddressip = InetAddress.getLocalHost();
Ip.getHostAddresss();//获得本地IP
Ip.getHostName();//获得本机名。
获得任意主机对象:
InetAddress ip =InetAddress.getByName(“192.168.1.2”)//传入任意主机IP地址,返回主机IP对象
UDP
将数据及源和目的封装成数据包中,不需要建立连接。
每个数据报的大小限制在64K以内。
因无连接,是不可靠协议。
不需要建立连接,速度快。
TCP
建立连接,形成传输数据的通道。
在连接中进行大数据量传输。
通过三次握手完成连接,是可靠协议。
必须建立连接,效率会稍低。
Socket
Socket就是为网络服务提供的一种机制。
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
【UDP数据发送小示例】:使用DatagramSocet和DatagramPacket来实现。
//发送端。
publicclass UdpSend{
publicstatic void main(String[] args) throws Exception{
//1.创建UDP服务,通过DatagramSocket
DatagramSocketds = new DatagramSocket();
//2确定数据,并封装成数据包。
byte[] buf =”shuju sended”.getBytes();
DatagramPacketdp = new DatagramPacket(buf,buf.length,InetAddress.getByName(“localhost”),10000);
//3通过socket服务将已有的数据包发送出去。
ds.send(dp);
//4关闭资源
ds.close();
}
}
//接受端
public classUdpRece{
public static void main(String[]args)throws Exception{
//1 创建udp socket 建立端点
DatagramSocket ds = newDatagramSocket(10000);//指定监听端口
While(true){
//2 定义数据包,用于存储数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
// 3通过服务的receive 方法将受到数据存入数据包中。
ds.receive(dp);
//4通过数据包的方法获取其中的数据
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(data);
}
//5 关闭资源
ds.close();
}
}
/**
* 编写一个聊天程序。
* 有收数据的部分,和发数据的部分。这两部分需要同时执行。
* 那就需要用到多线程技术。一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法。而且这两个方法要封装到不同的类中
*/
importjava.net.*;
importjava.io.*;
class Sendimplements 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();
DatagramPacketdp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10001);
this.ds.send(dp);
}
}
catch (Exception e)
{
throw newRuntimeException("发送端失败");
}
}
}
class Receimplements Runnable{
private DatagramSocket ds;
public Rece(DatagramSocket ds){
this.ds = ds;
}
public void run(){
try{
while(true){
byte[] buf= new byte[1024];
DatagramPacketdp = 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);
}
}
catch (Exception e)
{
throw newRuntimeException("接收端失败");
}
}
}
public classChatDemo
{
public static void main(String[]args)throws Exception{
DatagramSocket sendSocket =new DatagramSocket();
DatagramSocket receSocket =new DatagramSocket(10001);
new Thread(newSend(sendSocket)).start();
new Thread(newRece(receSocket)).start();
}
}
TCP传输:
1. Tcp分客户端和服务端。
2. 客户端对应的对象是Socket。服务端对应的对象是ServerSocket
通过查阅Socket对象,发现在该对象建立时,就可以去连接指定主机。因为tcp是面向连接的,所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
【示例1】步骤:
1. 创建Socket服务。并指定还要连接的主机和端口。
importjava.net.*;
importjava.io.*;
class TcpClient
{
public static void main(String[]args)throws Exception{
//创建客户端的socket服务,指定目的主机和端口
Socket socket = newSocket("localhost",10002);
//为了发送数据,应该获取Socket流中的输出流。
OutputStream out =socket.getOutputStream();
out.write("tcp ge menlai le!".getBytes());
socket.close();
}
}
/*
需求:定义端点接受数据并打印在控制台上。
1 创建服务端的socket服务,ServerSocket();并监听一个端口。
2 获取连接过来的客户端对象。
通过ServerSocket的accept方法。没有连接就会等。所以这个方法是阻塞式的。
3 客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。
4 关闭服务端。(可选操作)
*/
class TcpServer
{
public static void main(String[]args)throws Exception{
//创建服务端的socket服务,指定监听的端口
ServerSocket socket = newServerSocket(10002);
//通过accept方法获取连接过来的客户端对象。
Socket s = socket.accept();
String ip =s.getInetAddress().getHostAddress();
System.out.println(ip);
//获取客户端发送过来的数据,那么要使用客户端对象的读取流读取数据
InputStream in =s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(newString(buf,0,len));
s.close();
socket.close();//服务端关闭可选。
}
}
【示例2】
importjava.net.*;
importjava.io.*;
/*
演示tcp的传输的客户端和服务端的互访。
需求:客户端给服务端发送数据,服务端收到后给客户端反馈信息。
*/
/**
客户端
1 建立socket服务。指定要连接主机和端口
2 获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端
3 获取socket流中的输入流。将服务端的反馈信息获取到并打印。
4 关闭客户端资源。
*/
class TcpClient2
{
public static void main(String[] args)throws Exception
{
Socket s = newSocket("localhost",10003);
OutputStream out =s.getOutputStream();
out.write("服务端,你好".getBytes());
InputStream in =s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(newString(buf,0,len));
s.close();
}
}
class TcpServer2
{
public static void main(String[] args)throws Exception
{
ServerSocket ss = newServerSocket(10003);
Socket s = ss.accept();
String ip =s.getInetAddress().getHostAddress();
System.out.println(s);
InputStream in =s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(newString(buf,0,len));
Thread.sleep(10000);//服务端阻塞,客户端会等待服务端响应
OutputStream out =s.getOutputStream();
out.write("哥们收到,你也好".getBytes());
s.close();
ss.close();
}
}
BufferedReader对象的readLine方法是阻塞式方法,对方的输出流在write后务必使用newLine方法结束输入,然后flush刷新缓存。
TCP客户端和服务端相互等待的解决办法:Socket对象的shutdownOutput方法提供了结束输出的动作。客户端执行了shutdownOutout的方法则停止了继续输出,此时服务端也停止了读入!
- import java.net.*;
- import java.io.*;
- class TextClient
- {
- public static void main(String[] args) throws Exception
- {
- Socket s = new Socket("169.254.189.143",10006);
- BufferedReader bufr =
- new BufferedReader (new FileReader("IPDemo.java"));
- PrintWriter out = new PrintWriter (s.getOutputStream(),true);
- String line = null;
- while ((line=bufr.readLine())!=null)
- {
- out.println(line);
- }
- s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记。
- // out.println("over");
- BufferedReader bufIn =
- new BufferedReader (new InputStreamReader(s.getInputStream()));
- String str = bufIn.readLine();
- System.out.println(str);
- bufr.close();
- s.close();
- }
- }
- class TextServer
- {
- public static void main(String[] args) throws Exception
- {
- ServerSocket ss = new ServerSocket(10006);
- Socket s = ss.accept();
- String ip = s.getInetAddress().getHostAddress();
- System.out.println(ip+".....conneted!");
- //源:socket输入流
- 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)
- {
- // if ("over".equals(line))
- // break;
- out.println(line);
- }
- PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
- pw.println("上传成功");
- out.close();
- s.close();
- ss.close();
- }
- }
使用多线程处理多客户端并发访问服务端。服务端的accept接受客户端的连接后,启动对应的线程。从而避免多客户端并发访问时出现排队等待的情况。
URL类:
import java.net.*;
class URLDemo {
public static void main(String[] args) throws Exception{
URL url = newURL("http://www.itcast.cn/channel/video.shtml#java");
System.out.println(url.getHost());
System.out.println(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getPort());//默认80端口对应 -1
System.out.println(url.getProtocol());
System.out.println(url.getQuery());
}
}
URLConnection类:
import java.net.*;
import java.io.*;
class URLConnectionDemo{
public static void main(String[] args) throws Exception {
URL url = newURL("http://www.itcast.cn");
URLConnection conn = url.openConnection();
System.out.println(conn);
InputStream in = conn.getInputStream();
byte[] buf = new byte[1024];
int len = 0;
while((len = in.read(buf)) != -1)
System.out.println(newString(buf,0,len,"utf-8"));
}
}
InetSocketAddress:构造函数有一个参数backlog,代表允许最大的客户端连接数。