您的位置:首页 > 理论基础 > 计算机网络

Android使用Socket(Tcp/Udp)协议进行数据传输(传输大文件)

2016-08-31 13:38 1216 查看

Socket是什么:所谓Socket 通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。Socket内部又有两种协议(Tcp/Udp),我们来说说其各自的特点。

先来说说网络编程的三要素

1.IP地址:网络中计算机的唯一标识
2.端口
3.协议:通信的规则


Tcp/Udp特点

一、 TCP(协议):

建立连接,形成传输数据的通道

在连接中进行大数据量传输

通过三次握手完成连接,是可靠协议

必须建立连接,效率稍微低点

二. UDP(协议):

将数据及源和目的封装在数据包中,不需要建立连接

每个数据包的大小限制在64K内

因无连接,是不可靠协议

不需要建立连接,速度快

Socket工作图解



TCP协议进行数据传输,实现两台设备的一个简单数据发送。

客户端发送数据

/**
* @param serverAddress 要发送到服务端的ip
* 1.创建socket并指定ip和端口号
* 2.获取输出流,写数据
* 3.释放资源
* 4.Tcp一定要先开接收端
*/
public void send_tcp(String serverAddress) {
try {
Socket s = new Socket(serverAddress, WIFIAdmin.PORT);
//为了发送数据,应该获得socket流中的输出流
OutputStream out = s.getOutputStream();
out.write((content.getText().toString()).getBytes());
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


服务端接收数据

/**
* TCP协议接收数据
* 1.创建接收端的Socket对象
* 2.监听客户端接收,返回一个Socket对象
* 3.获取输入流,读取数据显示在控制台
* 4.释放资源
*/
public void receive_tcp() {
try {
//1.建立连接,监听端口
ServerSocket ss = new ServerSocket(WIFIAdmin.PORT);
//2.连接客户端对象
while (true) {
//阻塞式方法,只有客户端连接了才会继续往下运行
Socket accept = ss.accept();
//获取ip
String ip = accept.getInetAddress().getHostAddress();
//3.获取客户端发送过来的数据
InputStream in = accept.getInputStream();
//4.开始读取,获取输入信息
BufferedReader bff = new BufferedReader(new InputStreamReader(in));
//读取信息
String line;
final StringBuilder sb = new StringBuilder();
while ((line = bff.readLine()) != null) {
sb.append(line);
}
Message message = new Message();
message.obj = sb.toString();
handler.sendMessage(message);
//5.关闭
//ss.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}


现在来看下UDP协议是怎么进行数据传输的。

先来看下发送端

/*
* UDP协议发送数据:
* 1.创建发送端Socket对象
* 2.创建数据,并把数据打包
* 3.调用Socket对象发送方法发送数据包
* 4.释放资源
*/
private void udpSendMessage() {
DhcpInfo info = wifiManager.getDhcpInfo();
String serverAddress = WIFIAdmin.intToIp(info.serverAddress);
// 创建发送端Socket对象
try {
// 创建发送端Socket对象
DatagramSocket ds = new DatagramSocket();
// 创建数据,并把数据打包
byte[] bys = content.getText().toString().getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName(serverAddress),
WIFIAdmin.UDP_PORT);
// 调用Socket对象发送方法发送数据包
ds.send(dp);
// 释放资源
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}


在瞄一下接收端

/*
* UDP协议接收数据:
* 1.创建接收端Socket对象
* 2.创建一个数据包(接收容器)
* 3.调用Socket对象接收方法接收数据包
* 4.解析数据包
* 5.释放资源
*/
private void receive_udp() {
try {
// 创建接收端Socket对象
DatagramSocket ds = new DatagramSocket(WIFIAdmin.UDP_PORT);
// 创建一个数据包(接收容器)
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
// 调用Socket对象接收方法接收数据包
ds.receive(dp);
// 获取对方的ip
String ip = dp.getAddress().getHostAddress();
// 解析数据
String data = new String(dp.getData(), 0, dp.getLength());
Message message = new Message();
message.obj = data;
message.what = 2;
handler.sendMessage(message);
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}


使用Tcp协议传输大文件,循环将数据写入流中(Tcp发送端)

/*
* @param path     文件路径
* @param FileName 文件名
*/
public void sendFile(String path, String FileName) {
DhcpInfo info = wifiManager.getDhcpInfo();
serverAddress = WifiAdmin.intToIp(info.serverAddress);
Socket s = new Socket(serverAddress, PORT);
OutputStream out = s.getOutputStream();
//将文件名写在流的头部以#分割
out.write((FileName + "#").getBytes());
FileInputStream inputStream = new FileInputStream(new File(path));
byte[] buf = new byte[1024];
int len;
//判断是否读到文件末尾
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);//将文件循环写入输出流
}
//告诉服务端,文件已传输完毕
s.shutdownOutput();
//获取从服务端反馈的信息
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String serverBack = in.readLine();
Log.d("TAG", serverBack);
//资源关闭
s.close();
inputStream.close();

} catch (Exception e) {
e.printStackTrace();
}
}


大文件传输(Tcp接收端)

public synchronized void receiveFile() {
try {
ServerSocket ss = new ServerSocket(WifiAdmin.PORT);
while (true) {
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
int content;
//装载文件名的数组
byte[] c = new byte[1024];
//解析流中的文件名,也就是开头的流
for (int i = 0; (content = in.read()) != -1; i++) {
//表示文件名已经读取完毕
if (content == '#') {
break;
}
c[i] = (byte) content;
}
//将byte[]转化为字符,也就是我们需要的文件名
String FileName = new String(c, "utf-8").trim();
//创建一个文件,指定保存路径和刚才传输过来的文件名
OutputStream saveFile = new FileOutputStream(
new File(Environment.getExternalStorageDirectory().toString(), FileName));
byte[] buf = new byte[1024];
int len;
//判断是否读到文件末尾
while ((len = in.read(buf)) != -1) {
saveFile.write(buf, 0, len);
}
saveFile.flush();
saveFile.close();
//告诉发送端我已经接收完毕
OutputStream outputStream = socket.getOutputStream();
outputStream.write("文件接收成功".getBytes());
outputStream.flush();
outputStream.close();
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}


掌握了Socket的基本传输规则,相信你很快就能写出一个利用局域网让两台设备进行数据传输了。

最后附上Demo下载地址

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: