UDP传输数据特点
只需要一个目的地,然后将数据一直发送就行了。类似发快递
1.将数据及源和目的封装成数据包中,不需要建立连接
2.每个数据报的大小在限制在64k内
3.因无连接,是不可靠协议
4.不需要建立连接,速度快
(DatagramSocket 和 DatagramPacket类 )
TCP传输数据特点
3次握手确认后才可以传输,类似通话
1.建立连接,形成传输数据的通道。
2.在连接中进行大数据量传输
3.通过三次握手完成连接,是可靠协议
4.必须建立连接,效率会稍低
(Socket 和 ServerSocket类)
☆TCP传输最容易出现的问题
客户端连接上服务端,两端都在等待,没有任何数据传输。
通过例程分析:
因为read方法或者readLine方法是阻塞式。
解决办法:
自定义结束标记
使用shutdownInput,shutdownOutput方法。
实例 代码实现
UDP 从一个本机的一个端口发送信息(达哥,你可以的)到另一个端口
发送类
package cn.hncu.dage.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* @author<a href="mailto:953801304@qq.com">胡龙华</a>
* @version 2017-4-5 下午7:27:28
* @fileName SendDemo.java
*/
public class SendDemo {
public static void main(String[] args) {
try {
DatagramSocket ds =null;
//1.创建一个用来发送数据包的Socket (10000表示发送的端口号)
// 这里是封装你要发送的信息
ds = new DatagramSocket();
String str = "达哥,你可以的";
byte buf [] = str.getBytes();
//2.用一个数据包发发送数据,buf数据小于64K,然后要给发送的IP(机器号)以及接受软件的端口号(10001)
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("113.242.132.34"), 10001);
//3.调用一个方法发送
ds.send(dp);
// 4.关流
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
接收类
package cn.hncu.dage.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @author<a href="mailto:953801304@qq.com">胡龙华</a>
* @version 2017-4-5 下午8:23:57
* @fileName ReceiveDemo.java
*/
public class ReceiveDemo {
public static void main(String[] args) {
try {
// 1.创建一个接收数据的Socket 接收的端口号要与前面发送数据包的端口号一致,不然别找不到
DatagramSocket ds = new DatagramSocket(10001);
//2. 要创建一个数据包来接? 为什么呢?
/**
* 在网络中传输的是字节和字符,不是前面的数据包了,所以就需要新的数据包把数据收起来
*/
byte buf [] = new byte [1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//3.一个接收方法
ds.receive(dp);
//4.把接收的数据解析出来
/**法律意识
* 一定要追踪数据的来源地址,万一别人给你发反动信息呢?
* 网警抓了,你有来源地址就没事。
*/
// 来源IP和来源端口号
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String info = new String(dp.getData(),0,dp.getLength());
System.out.println("Ip地址为"+ip+"发来消息如下");
System.out.println(info);
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果
TCP 客户端发送消息到服务器,服务器发消息给客户端。就是通信
服务器代码
package cn.hncu.dage.TCP;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author<a href="mailto:953801304@qq.com">胡龙华</a>
* @version 2017-4-5 下午8:52:16
* @fileName MySocketSever.java
*/
public class MySocketSever {
public static void main(String[] args) {
// 1. 写个SeverSocket 指定端口 等待握手
try {
ServerSocket server = new ServerSocket(8888);
while (true) {
//2.握手通过一个accept() 方法可以得到发送 请求的线程
Socket s = server.accept();
// 读取客户端发来的信息
InputStream in = s.getInputStream();
byte bs[] = new byte[1024];
in.read(bs);
String ip = s.getInetAddress().getHostAddress();
System.out.println("客户端Ip为"+ip+"发来"+new String(bs));
// 向客户端发送消息
OutputStream out = s.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF("达哥,你是最棒的!!!");
dout.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端代码
package cn.hncu.dage.TCP;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author<a href="mailto:953801304@qq.com">胡龙华</a>
* @version 2017-4-5 下午9:01:50
* @fileName MySocketClient.java
*/
public class MySocketClient {
public static void main(String[] args) {
try {
Socket s = new Socket("113.242.132.34", 8888);
// 当能向下执行的时候说明请求成功了,否则请求失败就异常了
// 发送给服务器: 消息
OutputStream out =s.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
String str = "Yes,I can";
dout.writeUTF(str);
//接收来自服务器的消息
InputStream in = s.getInputStream();
DataInputStream din = new DataInputStream(in);
String str2 = din.readUTF();
System.out.println("服务器说:"+str2);
dout.close();
din.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果
下面再用两个端口,一个模拟客户端,一个模拟服务器,向服务器上传一个小文件
服务器代码并启动
package cn.hncu.dage.TCP.FilePass;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadTextServer {
public static void main(String[] args) throws IOException {
//1创建ServerSocket
ServerSocket s = new ServerSocket(7777);
//2获得握手方(客户端)对应的socket
Socket sk = s.accept();
//3读取客户端上传的文件数据----源:socket, 目的:本地磁盘
InputStream in = sk.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
PrintWriter pw = new PrintWriter(new FileWriter("c.txt"),true);
String str = null;
while( (str=br.readLine())!=null){
System.out.println("Server "+str);
pw.println(str);
}
DataOutputStream dout = new DataOutputStream(sk.getOutputStream());
dout.writeUTF("文件上传成功");
sk.close();
s.close();
}
}
客户端代码
package cn.hncu.dage.TCP.FilePass;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class UploadTextClient {
public static void main(String[] args) throws IOException {
Socket s = new Socket("113.242.142.12", 7777);
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
String str = null;
while( (str=br.readLine())!=null){
// pw.write(str);
// pw.flush(); // 刷缓存啊!!!
pw.println(str);
}
//★给服务器发送一个结束标记
s.shutdownOutput();
// 接收服务器消息
//接收服务器的应答消息
BufferedReader br2 = new BufferedReader( new InputStreamReader(s.getInputStream()) );
String info = br2.readLine();
System.out.println("server:"+info);
s.close();
}
}
开始只有a.txt 文件
然后 上传来了c.txt文件
对比两个文件
是完全相同的,当然,这里并不严谨没有考虑中文乱码问题。