客户端与服务器如何进行数据传输
感觉自己对于网络传输的问题一直很困惑。网上查阅的资料也不是自己想要的,所以只好到这里来求大神帮助!
最近在做聊天室,客户端是android,我自己在本地搭了workerman当做服务器。两边都是采用websocket协议。
我用inputstream读取txt文件通过websocket发送到服务器,服务器接受到数据后写入txt文件。这时txt文件正常能够打开。
现在我用同样的方法读取android录音出来的.amr文件发送到服务器并写入.amr文件中,会出现文件损坏无法打开的问题。
基于此,感觉自己平时只注重软件功能的实现而不注重计算机原理的弊端出现了。出现了一些自己也觉得很幼稚的问题:
1:网络之间是如何传输数据的?
我将音频文件读取出来转换成二进制传输到服务端,服务端怎么将这些二进制恢复成原来的文件呢?
2:如何解决上面说的文件损坏无法打开的问题?
还是说我的理解一开始就是错的,感觉将音频文件读取出来就是不行?而应该用什么方法将音频文件进行转换才能传送呢?
客户端android代码:
mConnection.connect(wsuri, new WebSocketHandler() {
@Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri);
InputStream is = null;
try {
is = new FileInputStream(_file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] bytes = new byte[1024];
int len = 0;
try {
while((len=is.read(bytes))!=-1)
{
Log.d(TAG, "senBinaryMessage: " + bytes);
mConnection.sendBinaryMessage(bytes);
}
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端代码:
$worker->onMessage = function($connection, $data)
{
$filePath="/Users/myname/Desktop/php/";
if (!file_exists($filePath)){//如果指定文件夹不存在,则创建文件夹
mkdir($filePath , 0777);
}
$name=$filePath.'voice'.'.amr';
$fp = fopen ($name,"a");
if (fwrite ($fp,$data)){
echo "写入模板成功";
} else {
fclose ($fp);
echo "写入模板失败!";
}
};
websocket Android workerman php
Answers
服务端代码不对,应该以追加的方式写文件
$worker->onMessage = function($connection, $data)
{
$filePath="/Users/myname/Desktop/php/";
if (!file_exists($filePath)){//如果指定文件夹不存在,则创建文件夹
mkdir($filePath , 0777);
}
$name=$filePath.'voice'.'.amr';
// ===这里要以追加的方式写文件===
file_put_contents($filePath.$name, $data, FILE_APPEND);
}
TCP工作方式:
https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%...
我认为文件损坏可能有两种原因
一. fopen 没有使用
b
标记
https://secure.php.net/manual/zh/function.fopen.php
在操作二进制文件时如果没有指定 'b' 标记,可能会碰到一些奇怪的问题,包括坏掉的图片文件以及关于 \r\n 字符的奇怪问题。
解决方法:
打开文件时加入
b
标记
php
fopen($name,"ab")
二. 写入成功后没有关闭文件。
这可能会导致:
1. 数据会停留在缓冲区,直到缓冲区已满或程序退出或垃圾回收时关闭文件才会把数据写入文件。(我太清楚php是否会对文件进行垃圾回收)
2. 可能程序退出或垃圾回收时关闭文件的顺序时随机的,这样将会导致数据前后顺序不一致。
用python做个测试
python3
a = open('test', 'ab') a.write(b'123') b = open('test', 'ab') b.write(b'456') b.close() a.close()
test文件的内容为:
456123
解决方法:
手动关闭文件
php
if (fwrite ($fp,$data)){ echo "写入模板成功"; } else { echo "写入模板失败!"; } fclose($fp);
或者使用
php
fflush($fp);
来将数据写入缓冲区
因为对php不熟,我没有进行测试。