概念:
互联网协议是在互联网中从一台计算机向另一台计算机传输数据的一种低层协议,数据是以包的形式封装的。两个和IP一起使用的较高层协议是
传输控制协议TCP和
用户数据报协议UDP。TCP能够让两台主机建立连接并交换数据流,确保数据的传送,也确保数据包以它们发送的顺序正确发送。UDP是一种用在IP之上的标准的、低开销的、无连接的、主机对主机的协议。
三大要素:
1、IP地址:InetAddress:网路中设备的标识;
2、端口号:用于标识进程的逻辑地址,不同进程的标识
有效端口号:0-65535,其中0-1024系统使用或保留端口;
2、端口号:用于标识进程的逻辑地址,不同进程的标识
有效端口号:0-65535,其中0-1024系统使用或保留端口;
3、传输协议:通讯规则。
不同:
UDP:
1、将数据及源和目的封装成数据包中,不需要建立连接;
2、每个数据包的大小限制在64k内;
3、因无连接,是不可靠协议;
4、不需要建立连接,速度快。
2、每个数据包的大小限制在64k内;
3、因无连接,是不可靠协议;
4、不需要建立连接,速度快。
TCP:
1、建立连接,行程传输数据的通道;
2、在连接中进行大数据量传输;
3、通过三次握手完成连接,是可靠连接;(服务端发出,客户端答应并反馈,服务端接收)
4、必须建立连接,效率会稍低。
2、在连接中进行大数据量传输;
3、通过三次握手完成连接,是可靠连接;(服务端发出,客户端答应并反馈,服务端接收)
4、必须建立连接,效率会稍低。
java支持基于流的通信和基于包的通信。基于流的通信使用TCP进行数据传输,而基于包的通信使用UDP。因为TCP协议能够发现丢失的传输信息并重新发送,所以,传输过程是无损的和可靠的。相对而言,UDP协议不能保证传输没有丢失,因此,大多数java程序设计采用基于流的通信。
java提供用于创建套接字的类来便于程序的网络通信。套接字Socket是两台主机之间逻辑连接的端点,可以用来发送和接收数据。
Socket:
1、Socket就是为网络服务提供的一种机制;
2、通信的两端都有Socket(网络通信其实就是Socket间的通信);
3、数据在两个Socket间通过IO传输。
2、通信的两端都有Socket(网络通信其实就是Socket间的通信);
3、数据在两个Socket间通过IO传输。
UDP小练习:完成一个简单的边写边打印出来的聊天程序。
这要用到多线程,一个线程在写,一个线程在读。
发送端:
public class Send implements Runnable{
DatagramSocket ds;
@Override
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while ((line=br.readLine()) != null) {
//将数据打包,进行封装
byte[] bytes = line.getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length,
InetAddress.getByName("IP地址"), 10006);
//如果输入端打出“886”,那就退出聊天,不能再输入
if (line.equals("886"))
break;
//传送数据包
ds.send(dp);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Send(DatagramSocket ds) {
this.ds = ds;
}
public Send() {
}
}
接收端:
public class Receive implements Runnable{
DatagramSocket ds;
public Receive() {
}
public Receive(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
while (true) {
//创建数据包
byte[] bytes = new byte[1024];
DatagramPacket pd = new DatagramPacket(bytes, bytes.length);
try {
//接收传送包
ds.receive(pd);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//读取包中的内容
byte[] buf = pd.getData();
//获取输入端的IP地址和端口号
String ip = pd.getAddress().getHostAddress();
int port = pd.getPort();
//打印输入端输入的内容
System.out.println(ip + ":" + port + ".................."
+ new String(buf, 0, buf.length));
}
}
}
主程序
public class Demo {
public static void main(String[] args) throws IOException {
Send s = new Send(new DatagramSocket());
Receive r = new Receive(new DatagramSocket(10006));
new Thread(s).start();启动线程
new Thread(r).start();;
}
}
UDP中的DatagramPacket是数据报包,它能把数据打包发送。需要注意的是,它能够指定端口。如果它一旦确定好了端口号,接收的端口便要一致,否则会发生异常。
TCP创建客户端:
1、创建TCP客户端Socket服务,使用的是Socket对象。建议该对象一创建就明确目的地。(注意的地方)
2、如果连接建立成功,说明数据传输通道已经建立。该通道底层是Socket流,是底层建立好的。可以通过getOutputStream和getInputStream来获取两个字节流。
3、使用数据流,将数据写出。
2、如果连接建立成功,说明数据传输通道已经建立。该通道底层是Socket流,是底层建立好的。可以通过getOutputStream和getInputStream来获取两个字节流。
3、使用数据流,将数据写出。
创建服务端:
1、创建服务端Socket服务,通过ServerSocket对象;(注意)
2、服务端必须对外提供一个端口,否则客服端无法连接。
1、创建服务端Socket服务,通过ServerSocket对象;(注意)
2、服务端必须对外提供一个端口,否则客服端无法连接。
小练习:完成将文本数据上传的小程序。
因为是文本数据,因而可以用上字符缓冲区和打印流。
客户端:
public class UploadSendTCP {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("IP地址",10009);
//读取文件的流缓冲区
BufferedReader br = new BufferedReader(new FileReader("F:IO\\a.txt"));
//Socket输出流
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
String line = null;
//读取文件中的内容,并封装进Socket流进行传输
while ((line = br.readLine()) != null) {
pw.println(line);
}
//结束标记,关闭Socket输出流,提示服务端上传结束
socket.shutdownOutput();
//读取服务端回传的信息
BufferedReader brIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String info = brIn.readLine();
System.out.println(info);
//关闭资源
br.close();
socket.close();
}
}
服务端:
public class UploadReceiveTCP {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10009);
//获取Socket对象
Socket s = ss.accept();
//要写入的文件
BufferedWriter bw = new BufferedWriter(new FileWriter("F:IO\\copy.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
//进行读取,并写入文件
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//结束后提示客户端已成功的标记
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
pw.println("上传成功!");
//关闭资源
bw.close();
ss.close();
}
}
需要注意的是,因是读取行的,Printwriter中须是pringln方法,否则读取时将会一直读取行分隔符,无法写入。且打印流要自动刷新,否则有可能只写入流中,而没有写进目的地。
其实TCP很大部分是和流结合在一起,只要对流的操作比较熟悉,对TCP只是附加将流和Socket进行连接,并且发送出去,终端再将流获取,读取里面的数据即可。