Archive

Archive for July, 2011

TCP链接主动关闭不发fin包奇怪行为分析

July 1st, 2011 3 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: TCP链接主动关闭不发fin包奇怪行为分析

问题描述:
多隆同学在做网络框架的时候,发现一条tcp链接在close的时候,对端会收到econnrest,而不是正常的fin包. 通过抓包发现close系统调用的时候,我端发出rst报文, 而不是正常的fin。这个问题比较有意思,我们来演示下:
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索, 网络编程 Tags: , ,

gen_tcp容易误用的一点解释

July 1st, 2011 5 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: gen_tcp容易误用的一点解释

前天有同学在玩erlang gen_tcp的时候碰到了点小麻烦,描述如下:

比如说连接到baidu.com,发个http请求,然后马上接收数据,发现接收出错,wireshark抓包发现数据都有往返发送,比较郁闷。

我把问题演示下:

 
$ erl
Erlang R14B03 (erts-5.8.4) [source] [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.4  (abort with ^G)
1> {ok,Sock} = gen_tcp:connect("baidu.com", 80, []).
{ok,#Port<0.582>}
2> gen_tcp:send(Sock, "GET / HTTP/1.1\r\n\r\n").
ok
3> gen_tcp:recv(Sock,0).
{error,einval}

这个问题的根源在于gen_tcp默认的{active,true},也就是说当gen_tcp收到网络包的时候,默认是把报文发送给它的宿主进程。而gen_tcp:recv是用户主动去拉数据,这二个模式是互斥的。

我们来看下代码otp/erts/emulator/drivers/common/inet_drv.c:7462

case TCP_REQ_RECV: {
..
        if (desc->inet.active || (len != 8))
            return ctl_error(EINVAL, rbuf, rsize);
..

那就解释为什么 gen_tcp:recv(Sock,0)返回错误码{error,einval}。
同时我们来验证下,报文是以消息的方式发送的。

 
4> flush().
Shell got {tcp,#Port<0.582>,
               "HTTP/1.1 400 Bad Request\r\nDate: Fri, 01 Jul 2011 03:51:25 GMT\r\nServer: Apache\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n127\r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>400 Bad Request</TITLE>\n</HEAD><BODY>\n<H1>Bad Request</H1>\nYour browser sent a request that this server could not understand.<P>\nclient sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /<P>\n</BODY></HTML>\n\r\n0\r\n\r\n"}
ok
5>

搞清楚了问题,那解决方案很简单,connect的时候把active模式设成{active,false}.
再来演示下:

$ erl
Erlang R14B03 (erts-5.8.4) [source] [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.4  (abort with ^G)
1> {ok,Sock} = gen_tcp:connect("baidu.com", 80, [{active,false}]).
{ok,#Port<0.582>}
2> gen_tcp:send(Sock, "GET / HTTP/1.1\r\n\r\n").
ok
3>  gen_tcp:recv(Sock,0).
{ok,"HTTP/1.1 400 Bad Request\r\nDate: Fri, 01 Jul 2011 05:25:15 GMT\r\nServer: Apache\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n127\r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>400 Bad Request</TITLE>\n</HEAD><BODY>\n<H1>Bad Request</H1>\nYour browser sent a request that this server could not understand.<P>\nclient sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /<P>\n</BODY></HTML>\n\r\n0\r\n\r\n"}
4> 

搞定!

玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索, 网络编程 Tags: ,

sysbench oltp测试MySQL问题

July 1st, 2011 3 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: sysbench oltp测试MySQL问题

昨天有同学在使用sysbench时候遇到了点小麻烦:

$ sysbench --test=oltp --oltp-table-size=100000000 --oltp-read-only=off --init-rng=on --num-threads=16 --max-requests=0 --oltp-dist-type=uniform --max-time=1800 --mysql-user=root   --db-driver=mysql --mysql-table-engine=innodb --oltp-test-mode=simple prepare
sysbench 0.4.12:  multi-threaded system evaluation benchmark

FATAL: unable to connect to MySQL server, aborting...
FATAL: error 1049: Unknown database 'sbtest'
FATAL: failed to connect to database server!
...

错误提示说:mysql连接不上, sbtest库没找到。

首先确认mysql是正常的…

$ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 91
Server version: 5.1.48-debug-log Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use sbtest;
ERROR 1049 (42000): Unknown database 'sbtest'

但是库 sbtest确实不存在。

通过查看sysbench-0.4.12/sysbench/drivers/mysql/drv_mysql.c:400行

  DEBUG("mysql_real_connect(%p, \"%s\", \"%s\", \"%s\", \"%s\", %u, \"%s\", %s)",
        con,
        host,
        args.user,
        args.password,
        args.db,
        args.port,
        args.socket,
        (MYSQL_VERSION_ID >= 50000) ? "CLIENT_MULTI_STATEMENTS" : "0"
        );
  if (!mysql_real_connect(con,
                         host,
                         args.user,
                         args.password,
                         args.db,
                         args.port,
                         args.socket,
#if MYSQL_VERSION_ID >= 50000
                          CLIENT_MULTI_STATEMENTS)
#else
                          0)
#endif

我们可以看到sysbench在连接的时候需要先连接到sbtest库,但是库不存在,所以出现问题。

解决问题的方法很简单:
在mysql的shell下运行:

create database sbtest;

搞定。

小结:开源软件总是有点小问题,自己动手丰衣足食!

玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: 工具介绍, 杂七杂八 Tags: ,