存档在 2014年5月

wget抓取整个ftp目录

2014年5月24日

wget支持ftp协议,是个很好的工具,刚好我也想把博客相关文件备份一下。
使用命令如下:

wget -m  -c -np ftp://帐号:密码@ftp地址  

-m 等价于–mirror ,相当于以下 -r -N -l inf -nr的组合,实现镜像复制;
-c continue,断点续传;
-np等价于–no-parent ,不进入父目录。
当然wget功能不仅仅限于此,想了解其他用法,可以点击这个链接查看,该链接会搜索博客中与wget相关的文章。

另外我通过wget将一个ftp站的好几十G资源全部给镜像下来了。

2014_05_21记录

2014年5月22日

今天是恩师黄老师生日,也是知己师兄和他老婆结婚一周年纪念日,值得庆贺。
黄老师是我最尊敬的人,感谢她在我研究生生涯给我的无微不至的关心,从来没有批评过我一次,给了我最宽松的学习工作环境。感谢你教我做人处事,应对婚姻。
石师兄是我研究生生涯最先认识的人,感谢他一路的照顾,感谢他每次的调解,和他一起做项目有一种默契,我将永远珍惜这份情谊。

20140521_185701

20140521_143731

20140521_185622

git提交空目录

2014年5月21日

git仅仅跟踪文件的变动,而不跟踪目录,导致一些必要的空目录不能加入到暂存区,最后不能提交到仓库。

解决的办法一般是在空目录总增加一个文件,有一种约定俗成的方法就是增加.gitignore文件,这个文件作为过滤器,可以存在工作目录的每个目录下。
可以通过以下脚本来检测空目录并自动生成一个.gitignore文件。

find . \( -type d -empty \) -and \( -not -regex ./\.git.* \) -exec touch {}/.gitignore \;

另外在手动创建.gitignore文件时,提示“必须键入文件名”,这是windows操作系统把.gitignore作为文件格式,误认为没有文件名,可以通过以下两种方式解决:
1.文件命名为”.gitignore.”
2.直接touch .gitignore

Code分享

2014年5月20日

1299

#include <stdio.h>
#include <stdlib.h>

int BSearchUpperBound(int array[], int low, int high, int target)
{
    if(low > high || target >= array[high]) return -1;

    int mid = (low + high) / 2;
    while (high > low)
    {
        if (array[mid] > target)
            high = mid;
        else
            low = mid + 1;

        mid = (low + high) / 2;
    }

    return mid;
}


int main()
{
    int n,m;
    int a[100];
    scanf("%d %d",&n,&m);
    for(int i = 0; i <n; ++i)
        scanf("%d",&a[i]);
    printf("%d\n",a[BSearchUpperBound(a,0, n-1,m)]);
    return 0;

}

1298

#include <stdio.h>
#include <stdlib.h>
#define min(a,b) ((a) >(b)?(b):(a))
int coin[]= {2,3,5};
int fun(int n)
{
    if(n == 1)
        return 1;
    else if(n==3)
        return 1;
    else if(n==5)
        return 1;
    else
    {
        int m = 0xffff;
        for(int i = 0; i < 3; i++)
        {
            if(n >= coin[i])
                m = min(m,fun(n-coin[i]) + 1);
        }
        return m;
    }
}

VS2012-2005版本.sln文件头部标志信息

2014年5月20日

高版本的VS能够对低版本的VS解决方案进行转换后打开,而低版本的VS则不能直接打开高版本的VS解决方案,其实就解决方案中某个工程来说,各个版本的编译器并没有差别。
所以在需要低向高转换的时候,可以尝试一下修改.sln解决方案文件,或许问题就解决了。
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005

BUG报告:线程死锁

2014年5月15日

一段帧的完整性匹配算法,有线程死锁的情况,在该文的第23行的continue应为break;

原因分析:
当循环队列中数据个数少于2时,消费者线程一直执行if(cir.size() < 2) continue,在执行的同时还占有锁;在生产者端有数据要放入循环队列时,试图获得互斥锁失败,导致数据插入循环队列失败。最终的结果是消费者线程一直饥饿等待数据到来,生产者有很多数据但是不能获得锁而不能产生数据。

Qt中使用中文注释产生的奇异问题

2014年5月15日

在使用Qt编写一个状态指示灯时,定义了类中嵌套的结构体,使用了如下的代码:

struct HLed::Private
{
public:
    enum LightState{ON, OFF, ERR};
    Private(): color(Qt::green), lightState(ON){}
    //灯的颜色
    QColor color;
    //灯的状态
    LightState lightState;
};

编译提示以下错误:

error: C2614: “HLed::Private”: 非法的成员初始化:“lightState”不是基或成员

对于一个以C++作为母语的人来说,我确实不能发现哪里有问题。在我重敲代码后,奇迹般的错误没有了,对比前后的异同,发现是注释引起,修改成这样就行了

struct HLed::Private
{
public:
    enum LightState{ON, OFF, ERR};
    Private(): color(Qt::green), lightState(ON){}
    QColor color;
    LightState lightState;
};

结论:Qt对中文的兼容性还不太好,在程序中使用中文时,当字数为奇数时会出现乱码,不得不将字数凑偶,有时候甚至偶数个字数也会出现错误。

Mult-Echo转发服务器

2014年5月13日

GPRS模块的数据需要发送到本地控制台,与传统的GSM模块以短信作为传输媒介传输不同,这种方案按理想状态有以下两种方式:
(要找一台公网IP的服务器还是很不容易,网上找则需要花钱,刚好我家里的电脑是ADSL拨号,有公网IP,将服务器部署在上面最好不过)

1.GPRS模块之间可通信
但是事实上除非花大钱购买专有IP,否则现在还不能做到点对点的通信,即使是在PC机上完成P2P,也是需要第三方公网服务器的协调才能完成。以下为这种理想情况的框架图。
1

2.通过第三方公网服务器转发
如果GPRS点之间可以通信,那么可以使用该服务器来协调P2P的建立。但是实际上并不能点对点通信,所以只有选择通过第三方服务器的转发。以下是可实现的框架图。
3

作为公网转发服务器,要克服GPRS模块建立网络后容易异常掉线这种情况。当然作为服务器端,功能需求非常少,只需转发即可,代码也就很简单了。

package reflectServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Echo-transfer服务器
 */
public class EchoServer {

	private final static int BUFFER_SIZE = 512;
	private final static int PORT = 3333;
	private Selector selector = null;
	private ServerSocketChannel ssc = null;

	public static void main(String[] args) throws IOException {
		EchoServer server = new EchoServer();
		server.start();
	}

	private static void print(String s) {
		System.out.println(s);
	}

	private List<SocketChannel> socketsChanel = new ArrayList<SocketChannel>();

	public void pop(SocketChannel sc) {
		socketsChanel.remove(sc);
	}

	public void push(SocketChannel sc) {
		socketsChanel.add(sc);
	}

	public EchoServer() throws IOException {
		selector = Selector.open();
		ssc = ServerSocketChannel.open();
		ssc.socket().bind(new InetSocketAddress(PORT));
		ssc.socket().setReuseAddress(true);
		ssc.configureBlocking(false);
		ssc.register(selector, SelectionKey.OP_ACCEPT);
		print("服务器启动,准备好连接...");
	}

	public void start() throws IOException {
		ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
		
		while (selector.select() > 0) {
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			for (SelectionKey key : selectionKeys) {
				if (key.isAcceptable()) {
					SocketChannel sc = ssc.accept();
					print("有新的连接!地址:" + sc.socket().getRemoteSocketAddress());
					sc.configureBlocking(false);
					sc.register(selector, SelectionKey.OP_READ);
					push(sc);
				}

				if (key.isReadable()) {
					SocketChannel sc = (SocketChannel) key.channel();
					//print("有新的读取!地址:" + sc.socket().getRemoteSocketAddress());
					buffer.clear();
					try {
						int bytes = sc.read(buffer);
						if (-1 == bytes) {
							print("连接断开");
							key.cancel();
							sc.close();
							pop(sc);
							continue;
						}
					} catch (Exception e) {
						pop(sc);
					}

					buffer.flip();
					/*byte[] b = new byte[buffer.limit()];
					buffer.get(b);
					String s = new String(b);
					print("读取的内容为:" + s);
					buffer.clear();
					s = "echo: " + s;
					buffer.put(s.getBytes());
					buffer.flip();*/
					//print("共有多少套接字连接:" + socketsChanel.size());
					for (SocketChannel socketSend : socketsChanel) {
						if (socketSend != sc)
							try {
								socketSend.write(buffer);
								buffer.flip();
							} catch (Exception e) {
								pop(socketSend);
								e.printStackTrace();
								break;
							}
					}
				}
			}
			selectionKeys.clear();
		}
	}
}