在java中网络程序有两种协议:
TCP和UDP,TCP通过握手协议进行可靠的连接,UDP则是不可靠连接。
IP地址:用于标记一台计算机的身份证。
IP地址由网络地址(确定网络)和主机地址(网络中的主机)组成。
子网掩码:为了区分网络地址和主机地址。
IP地址分为A类地址、B类地址、C类地址(常用)、D类地址、E类地址。
127.0.0.1(localhost)是本机地址。
IPV4和IPV6
IPV4使用4个十进制数表示,即32位二进制。
SMTP是简单邮件传输协议,端口号是25.
telnet用于连接远程计算机或者因特网计算机提供的服务。每个服务都会设定一个端口。
给出类似 telnet ip port 即可和特定的服务进行通信
如果要连接因特网的服务,不仅要给出端口,还要给出计算机的名称,只有给出IP地址和端口号时,才能够请求服务,并接收到应答。
网络传输方式:
主要有:
tcp
Udp
Tcp和Udp的对比
UDP:
1. 将数据即源头和目的的封装成数据包中,不需要建立连接
2. 每个数据报的大小在限制在64k内
3. 因无连接,是不可靠协议
4. 不需要建立连接,速度快
TCP:
1. 建立连接,形成传输数据的通道
2. 在连接中进行大数据量传输
3. 通过三次握手完成连接,是可靠协议
4. 必须建立连接,效率会很低
关于InetAddress
根据域名得到IP地址或名称
1. InetAddress i1 =InetAddress.getByName(String)返回一个InetAddress实例。
2. 如果一个地址有多个ip地址,比如google,有3个ip地址,就调用InetAddress[]i2 = InetAddress.getAllByName(String);
InetAddress.getLocalhost()获得本机的InetAddress实例。
实例:
import java.net.*;//java关于网络的jar文件都封装net包下面,所以必须导入
public class Test1
{
public static voidmain(String[] args) throws Exception
{
InetAddressi=InetAddress.getLocalHost();//getLocalHost()返回本地主机
System.out.println(i);//WIN-UL3E91DKQ6C/192.168.1.103
System.out.println("address:"+i.getHostAddress());//192.168.1.103
System.out.println("name:"+i.getHostName());//WIN-UL3E91DKQ6C
//通过主机名获取ip地址
InetAddressia=InetAddress.getByName("www.baidu.com");
// getByName() 返回此 InetAddress 对象的原始 IP 地址。
System.out.println(ia.getHostAddress());//返回 IP 地址字符串(以文本表现形式)
System.out.println(ia.getHostName());//获取此 IP 地址的主机名。
}
}
ava中的socket
Socket是一个用于机器之间通信的类。
Socket客户端:
1. Socket s= new Socket(ip,port);打开一个套接字,发送请求
2. InputStream istream = s.getInputStream();接收数据
3. OutputStream ostream = s.getOutputStream();发送数据
需要用PrintWriter和Scanner进行包装,并且注意PrintWriter的自动缓冲。
Socket服务器:注意多个客户端同时访问服务器的问题:多线程
1. ServerSocketserver = new ServerSocket(port);创建一个端口
2. Sockets = server.accept(); 只有当有客户端请求并连接,函数才会返回
3. InputStreamistream = s.getInputStream();接收数据
4. OutputStream ostream =s.getOutputStream();发送数据
需要用PrintWriter和Scanner进行包装,并且注意PrintWriter的自动缓冲
UDP传输的流程总结
1. DatagramSocket与DatagramPacket
2. 建立发送端,接收端
3. 建立数据包
4. 调用Socket的发送和接收方法
5. 关闭Socket
实例:
需求:通过Udp传输方式,将一段文件数据发送出去
思路:
1.建立udpsocket服务
2. 提供数据,并将数据封装到数据包中
3. 通过socket服务的发送功能,将数据包发出去
4. 发送出去
import java.net.*;
class Test2
{
publicstatic void main(String[] args) throws Exception
{
//1:建立updsocket服务
DatagramSocketds=new DatagramSocket();
//2.确定数据,并封装成数据包
byte[]data="udp ge men lai le".getBytes();
DatagramPacketdp=new DatagramPacket(
data,
data.length,
InetAddress.getByName("192.168.1.103"),
3000);
//3.通过socket服务将已有的数据包发送出去
ds.send(dp);
//4.关闭资源
ds.close();
}
}
实例: 需求:
定义一个应用程序,用于接收udp协议传输的数据并进行处理
思路:
1.定义udpsocket服务
2.定义一个数据包,因为要存储接收到的字节数据
因为数据包对象中有跟多的功能可以提前字节数据中的不同数据信息
3.通过socket服务的recive方法将接收到的数据存入已经定义好的数据包中
4.通过数据包中的特有功能将这些不同的数据取出,打印在控制台上
import java.net.DatagramPacket;
import java.net.DatagramSocket;
class Test3
{
publicstatic void main(String[] args) throws Exception
{
//1.创建udp,socket,建立端点
DatagramSocketds=new DatagramSocket(3000);
//2.定义数据包,接收数据
byte[]buf=new byte[64*1024];
DatagramPacketdp=new DatagramPacket(buf, buf.length);
while(true)
{
//3.接收,将数据存入到包中
ds.receive(dp);
//4.通过数据包的方法取出数据
System.out.println("ip:"+dp.getAddress().getHostAddress());
System.out.println("data:"+newString(dp.getData(),0,dp.getLength()));
System.out.println("port:"+dp.getPort());
}
}
}
实例:
键盘循环发送,接收端可以循环接收
import java.io.*;
import java.net.*;
/*
*
*/
public class UdpSend2
{
publicstatic void main(String[] args) throws Exception
{
DatagramSocketds=new DatagramSocket();
BufferedReaderbr=new BufferedReader(new InputStreamReader(System.in));
Stringline=null;
while((line=br.readLine())!=null)
{
if("886".equals(line))
break;
byte[]buf=line.getBytes();
//将ip地址改为 192.168.1.255 表示广播,想这个192.168.1网段用户发送
DatagramPacketdp=newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.103"),10001);
ds.send(dp);
}
}
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpRecive2
{
publicstatic void main(String[] args) throws Exception
{
DatagramSocketds=new DatagramSocket(10001);
while(true)
{
byte[]buf=new byte[1024*64];
DatagramPacketdp=new DatagramPacket(buf,buf.length);
ds.receive(dp);
Stringip=dp.getAddress().getHostAddress();
intport=dp.getPort();
Stringcontent=new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port+"\n"+content);
}
}
}
Tcp传输
1. Socket和ServerSocket
2. 建立客服端和服务器端
3. 建立连接后,通过Socket中的IO流进行数据的传输
4. 关闭socket
同样,客服端和服务器端就是两个独立的应用程序
实例:
/*
* 演示Tcp出传输
* 1. tcp分为客户端和服务端
* 2. 客服端对应的是socket
* 服务器端对应的是ServerSocket
*
* 客服端:
* 通过查阅socket对象,发现对象建立时,就可以去连接指定的主机
* 因为tcp是面向连接的,所以建立socket服务时
* 就要有服务端存在,并连接成功,形成通路,在该通道进行数据的传输
*
* 需求:给服务器发送一个文本数据
* 步骤:
* 1.创建Socket服务,并指定要连接的主机和端口
*/
客服端
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
importjava.net.UnknownHostException;
public class Test6
{
public static voidmain(String[] args) throws Exception
{
//创建客服端的socket服务,指定目的主机和端口
Sockets=new Socket("192.168.1.103",10003);
//为了发送数据,应该获取socket流中的输出流
OutputStreamout=s.getOutputStream();
out.write("tcpge men lai le ".getBytes());
s.close();
}
}
服务器端程序
/*
* 需求:定义断点接收数据并打印在控制台上
* 服务端
* 1.建立服务服务端的socket,ServerSocket,并监听一个端口
* 2. 获取连接过来的的客服端对象
* 通过ServerSocket的accept方法,所以这个方法是阻塞式的
* 3. 如果客户端发过来数据,那么服务端要使用对应的客服端对象,
* 并获取改客服端对象读取流发过来的数据
* 4.关闭服务端
*/
mport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Test7
{
public static voidmain(String[] args) throws Exception
{
//建立服务端socket服务,并监听一个端口
ServerSocket ss=newServerSocket(10003);
//通过accept方法获取客服端对象
Socket s=ss.accept();
//获取客服端发过来的数据,那么要使用客服端对象的读取流来读取数据
InputStreamin=s.getInputStream();
byte[] buf=new byte[1024];
int len=in.read(buf);
System.out.println(s.getInetAddress().getHostAddress());
System.out.println("内容:"+newString(buf,0,len));
//关闭客服端
s.close();
}
}
实例
客户端给服务端发送数据,服务端接收到后,给客户端反馈信息
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
importjava.net.UnknownHostException;
//演示tcp的传输的客服端和服务器端的互访
/*
* 需求是:客户端给服务端发送数据,服务端接收到后,给客户端反馈信息
*
* 客服端
* 1.建立socket服务,指定要连接主机和端口
* 2.获取socket流中的输出流,将数据写到该流中,通过网络发送给客服端
* 3.获取客服端输入流,将服务端反馈信息获取到,并打印
* 4.关闭客服端资源
*
*/
public class Test8
{
public static voidmain(String[] args) throws Exception
{
Sockets=new Socket("192.168.1.103", 30009);//指定发送目的ip和端口
OutputStreamout=s.getOutputStream();//获取输出对象
out.write("服务端,你好!".getBytes());//写入数据
InputStreamin=s.getInputStream();
byte[]buf=new byte[1024];
intlen=in.read(buf);//读到缓冲区
System.out.println(newString(buf,0,len));//打印
s.close();
}
}
服务器端
java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Test9
{
public static voidmain(String[] args) throws Exception
{
ServerSocketss=new ServerSocket(30009);
Sockets=ss.accept();//得到来请求的soket对象
InputStreamin=s.getInputStream();/得到请求对象的输入流
byte[]buf=new byte[1024];
intlen=in.read(buf);//读取输入流的内容
System.out.println(s.getInetAddress().getHostAddress());//获取详细信息
System.out.println(newString(buf,0,len));
OutputStreamout=s.getOutputStream();
out.write("你也好!".getBytes());
s.close();
}
}
实例:
建立一个远程文本转换服务器
/*
* 需求:建立一个文本转换服务器
* 客户端发送文本,服务端会将文本转换成大写返回给客服端
* 而且客服端可以不断的进行文本的转换,当客服端输入over时,转换结束
*
* 分析:
* 客服端:
* 既然是操作设备上的数据,那么就是可以使用io技术,并按照io操作的规律来思考
* 目的:网络设备
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Test10
{
public static voidmain(String[] args) throws Exception
{
Socket s=newSocket("192.168.1.103",20009);
//定义键盘输入流对象
BufferedReaderbr=new BufferedReader(new InputStreamReader(System.in));
//定义目的,将socket的输入流发给服务端
BufferedWriterbw=new BufferedWriter(newOutputStreamWriter(s.getOutputStream()));
//定义一个socket读取流,读取服务器返回的大写信息
BufferedReaderbReader=new BufferedReader(newInputStreamReader(s.getInputStream()));
Stringline=null;
while((line=br.readLine())!=null)
{
if("over".equals(line))
break;
//没有发送回车符
bw.write(line);
bw.newLine();//一定要加上换行符
bw.flush();
Stringstr=bReader.readLine();
System.out.println("server:"+str);
}
bw.close();
bReader.close();
s.close();
}
}
服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.BreakIterator;
//服务端返回大写格式的信息
public class Test11
{
public static voidmain(String[] args) throws Exception
{
ServerSocket ss=new ServerSocket(20009);
Socket s=ss.accept();
//读取socket流中的数据
BufferedReader br=newBufferedReader(new InputStreamReader(s.getInputStream()));
//BufferedWriter bw=newBufferedWriter(newOutputStreamWriter(s.getOutputStream()));
//改成打印流,改进:打印流既可以接收字符流,也可以接收字节流,还能自动刷新
PrintWriter out=newPrintWriter(s.getOutputStream(),true);
String line=null;
while((line=br.readLine())!=null)
{
out.println(line.toUpperCase());
/*
* bw.write(line.toUpperCase());
* bw.newLine();//一定要加入换行符
bw.flush();//刷新
*/
}
s.close();
ss.close();
}
}
/*
* 该例子出现的问题:
* 客服端和服务端都在莫名的等待
* 因为客服端和服务端倪都有阻塞式的方法,如果没有结束标记(换行符),就会一直等
*/