最近了解了下下socket方面的东西,想做一个socket上传文件的例子。

在网上搜了搜代码执行后,图片数据传输了一半,图片的下半部分是灰色的。然后就自己仿着搜来的代码和php.net 中socket方法的介绍写了一个可以完整上传文件的代码。这里以图片为例。

client.php

/**
* client.php
*/
define("token", "1k8o3u4h5t6uv8a53uz4210mz"); # 通过appkey 与appsecret动态生成上传凭证,
$filePath = "C:\\Users\\Administrator\\Desktop\\socketIMg\\";
$fileName = "chorme.png";
$fp = fsockopen("127.0.0.1", 1688, $errno, $errstr, 30);
if (is_resource($fp)) {
$fileSize = filesize($filePath . $fileName);
fwrite($fp, json_encode(['filename' => $fileName, 'filesize' => $fileSize, 'token' => token])); # 发送文件名、上传凭证、文件大小
$out = file_get_contents($filePath . $fileName);
$receiveFileSize = fwrite($fp, $out); # 发送文件if ($receiveFileSize == $fileSize) {
echo 'send success';
} else {
echo 'data uncomplete!';
} // while (!feof($fp)) {
// echo fgets($fp, 128);
// }
fclose($fp);
}

server.php

/**
* server.php
*/
define("token", "1k8o3u4h5t6uv8a53uz4210mz"); # 约定好的token凭证,通过appkey动态生成,这里演示固定值
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 1688);
$listening = socket_listen($socket);
if ($listening) {
echo "status OK \r\n";
} else {
echo "fail";
exit();
}
while (true) {
$connection = socket_accept($socket);
if ($connection) {
$buffer = '';
$begin = TRUE;
$fileSize = 0; # 接收的数据大小
$sendFilesize = 0; # 发送文件自带文件大小
while (socket_recv($connection, $buffer, 1024, 0)) { # 一直保持连接且接受数据,1024字节大小为一个接收包
if ($begin) { # 客户端发送文件名,
$fileInfo = json_decode($buffer, TRUE);
if ($fileInfo['token'] != token) {
echo "token valid false !\r\n";
break;
}
$file_name = $fileInfo["filename"];
$sendFilesize = $fileInfo["filesize"];
$fp = fopen($file_name, "wb"); //写入方式+二进制模式写入
if (!$fp) {
echo "Create file error!\r\n";
break;
}
$begin = FALSE;
continue;
}
#客户端发送 文件数据,fwrite 写入数据
$fileSize+=strlen($buffer);
fwrite($fp, $buffer);
} # 发送大小与接收大小相同=保存成功
if ($sendFilesize != 0 && $fileSize == $sendFilesize) {
echo "receive success!\r\n";
} else {
echo "receive fail!\r\n";
}
#socket_write($connection, "aaa", strlen("aaa"));
isset($fp) && fclose($fp);
socket_close($connection);
}
}
socket_close($socket);

cmder 切换到server.php目录路径

在看s1根目录下文件:

问题:

上传文件成功后,服务端应该给客户端返回一个响应,通过socket_write发送。客户端通过fgets接收,但是打开代码中注释的:

socket_write($connection, "aaa",  strlen("aaa"));
     while (!feof($fp)) {
echo fgets($fp, 128);
}

会直接导致程序堵塞,暂未解决fgets堵塞发方法。

昨天又看了个workerman PHP socket 服务器框架   的确很“socket” ,不用手写了,用到socket功能的鞋童建议直接使用这个框架。

在workerman给的手册中也有上传文件的例子,在这里我把文件搬过来。

链接: http://doc3.workerman.net/protocols/example.html

新建协议查看文档说明,目录结果如下:

跟目录放一个漂亮的美女图片,新增一个tmp目录

我们先用二进制方法上传文件

打开cmder运行 :php upimgserBinary.php启动服务

cmder 运行uploadclientBinary.php +文件001.jpg

提示上传成功,查看tmp目录是否有图片

相同的方法执行text协议上传。

代码如下:

upimgserBinary.php

use Workerman\Worker;
require_once dirname(__DIR__) . '/Workerman/Autoloader.php'; $worker = new Worker('BinaryTransfer://0.0.0.0:8333');
// 保存文件到tmp下
$worker->onMessage = function($connection, $data)
{
$save_path = 'tmp/'.$data['file_name'];
file_put_contents($save_path, $data['file_data']);
$connection->send("upload success. save path $save_path");
}; Worker::runAll();

uploadclientBinary.php

/** 上传文件客户端 **/
// 上传地址
$address = "127.0.0.1:8333";
// 检查上传文件路径参数
if(!isset($argv[1]))
{
exit("use php client.php \$file_path\n");
}
// 上传文件路径
$file_to_transfer = trim($argv[1]);
// 上传的文件本地不存在
if(!is_file($file_to_transfer))
{
exit("$file_to_transfer not exist\n");
}
// 建立socket连接
$client = stream_socket_client($address, $errno, $errmsg);
if(!$client)
{
exit("$errmsg\n");
}
// 设置成阻塞
stream_set_blocking($client, 1);
// 文件名
$file_name = basename($file_to_transfer);
// 文件名长度
$name_len = strlen($file_name);
// 文件二进制数据
$file_data = file_get_contents($file_to_transfer);
// 协议头长度 4字节包长+1字节文件名长度
$PACKAGE_HEAD_LEN = 5;
// 协议包
$package = pack('NC', $PACKAGE_HEAD_LEN + strlen($file_name) + strlen($file_data), $name_len) . $file_name . $file_data;
// 执行上传
fwrite($client, $package);
// 打印结果
echo fread($client, 8192),"\n";

------------------------

upimgserText.php

use Workerman\Worker;
require_once dirname(__DIR__) . '/Workerman/Autoloader.php'; $worker = new Worker('TextTransfer://0.0.0.0:8333');
// 保存文件到tmp下
$worker->onMessage = function($connection, $data)
{
$save_path = 'tmp/'.$data['file_name'];
file_put_contents($save_path, $data['file_data']);
$connection->send("upload success. save path $save_path");
}; Worker::runAll();

uploadclientText.php

/** 上传文件客户端 **/
// 上传地址
$address = "127.0.0.1:8333";
// 检查上传文件路径参数
if(!isset($argv[1]))
{
exit("use php client.php \$file_path\n");
}
// 上传文件路径
$file_to_transfer = trim($argv[1]);
// 上传的文件本地不存在
if(!is_file($file_to_transfer))
{
exit("$file_to_transfer not exist\n");
}
// 建立socket连接
$client = stream_socket_client($address, $errno, $errmsg);
if(!$client)
{
exit("$errmsg\n");
}
stream_set_blocking($client, 1);
// 文件名
$file_name = basename($file_to_transfer);
// 文件二进制数据
$file_data = file_get_contents($file_to_transfer);
// base64编码
$file_data = base64_encode($file_data);
// 数据包
$package_data = array(
'file_name' => $file_name,
'file_data' => $file_data,
);
// 协议包 json+回车
$package = json_encode($package_data)."\n";
// 执行上传
fwrite($client, $package);
// 打印结果
echo fread($client, 8192),"\n";

打包的7zip附件文件:

http://files.cnblogs.com/files/dcb3688/workerman-upload-file.7z

PHP socket上传文件图片的更多相关文章

  1. php 利用socket上传文件

    php 利用socket上传文件 张映 发表于 2010-06-02 分类目录: php 一,利用fsockopen来上传文件 以前我写过一篇关于socket通信原理的博文http://blog.51 ...

  2. ASP.NET、JAVA跨服务器远程上传文件(图片)的相关解决方案整合

    一.图片提交例: A端--提交图片 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string u ...

  3. 基于spring-boot的web应用,ckeditor上传文件图片文件

    说来惭愧,这个应用调试,折腾了我一整天,google了很多帖子,才算整明白,今天在这里做个记录和分享吧,也作为自己后续的参考! 第一步,ckeditor(本博文论及的ckeditor版本4.5.6)的 ...

  4. 通过PHP CURL模拟请求上传文件|图片。

    现在有一个需求就是在自己的服务器上传图片到其他服务器上面,过程:客户端上传图片->存放到本地服务器->再转发到第三方服务器; 由于前端Ajax受限制,只能通过服务器做转发了. 在PHP中通 ...

  5. elementUI 上传文件图片大小加了限制后 仍然上传了

    https://blog.csdn.net/chanlingmai5374/article/details/80558444  看了这位老哥的说法 在看看文档 才发现自己没认真看文档 <el-u ...

  6. 【2】通过Ajax方式上传文件(图片),使用FormData进行Ajax请求

    HTML: <form id= "uploadForm"> <p >指定文件名: <input type="text" name= ...

  7. ajaxfileupload批量上传文件+图片尺寸限制

    1.首先展示ajaxfileupload代码,在这里修改为批量上传 //ajaxfileupload不展示全部代码,这是修改前与修改后代码对比,目的是上传多个文件 createUploadForm: ...

  8. socket 上传文件

    """ "" server.py """服务端 """import socketimpor ...

  9. 利用Common-Fileupload上传文件图片

    一,介绍 common-fileupload是appache的开源组件,基于该组件可以轻松实现文件上传的功能,strust框架的文件上传功能也是基于该组件. 二,使用 1,导入两个jar包:commo ...

随机推荐

  1. vue-router2使用

    条件:紧接前面vue.js开发环境搭建 1.在cmd输入:npm install vue-router,回车,等待,安装对应版本router: 2.在入口文件用 import vueRouter fr ...

  2. Sed、Awk单行脚本快速参考

    文本间隔: # 在每一行后面增加一空行 sed G awk '{printf("%s\n\n",$0)}' # 将原来的所有空行删除并在每一行后面增加一空行. # 这样在输出的文本 ...

  3. OpenStack三种类型的NAT转换

    SNAT SNAT即源网络地址转换,这个NAT路由修改IP包包头中的源IP地址.SNAT功能通常用于让只具有私有IP地址的主机能够访问外网,比如,多个PC使用路由器共享上网,每个PC都配置了内网IP, ...

  4. TinkPad E40 CentOS 6.5 无线网卡驱动 RTL8191SEvB 安装

    最近把一台老本TinkPad E40 安装了CentOS 6.5 其他都没什么问题,唯独没有无线网卡驱动. 通过命令: lspci | grep Network 查看无线网卡型号: 然后去瑞昱官网找驱 ...

  5. [原创]webapp/css3实战,制作一个《炉石传说》宣传页

    在移动网页,尤其是webapp中常需要用到大量的css3动画,来获得良好交互体验 我之前帮朋友做了一个,可惜没帮上忙现在和大家分享一下 目标是要做一个<炉石传说>游戏的介绍宣传页面,文字内 ...

  6. 关于JavaScript初级的知识点一(持续更新 )

    自己刚开始接触JS这是自己一个多月以来的一些总结和回顾. 一.什么是js? js是一种弱类型的脚本语言,是HTML的3大组成部分之一.HTML标签 CSS样式 JS脚本. 二.js的5种基本数据类型 ...

  7. Markdown编辑器:Typora

    现在网上的Markdown有很多,各有各的特色,同时也有各自的缺点.比如有的传图片比较麻烦,有的导出pdf需要付费,有的数学公式编辑比较麻烦等等...... 而最近接触到Typora,发现这真是一款良 ...

  8. Linux文件与目录管理

    .      代表此层目录 . .     代表上一层目录 -      代表前一个工作目录 ~     代表"目前用户身份"所在的中文件夹 ~account   代表accoun ...

  9. powershell使用

    主要语法点: -match -notmatch -replace -join -split -and -or -xor -not ! +.-.*./.% =.+=.-=.*=./=.%= -eq.-n ...

  10. php mysqli mysqli_query() mysqli_real_query()

    2016年11月26日 15:22:27 星期六 场景: PHP从mysql中读取数据 1. 一次性读取所有数据返给PHP 2. 每次循环只读取一掉记录 数据量小的时候可以使用第一种方法, 数据量很大 ...