九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

以此纪念刚开始在linux上学习网络编程的失败-_-!

以此纪念刚开始在linux上学习网络编程的失败-_-!

write by九天雁翎(JTianLing) – www.jtianling.com**

讨论新闻组及文件

 

从一开始的学习到现在,我的Ubuntu 8.04服务器版本就从来没有正常的跑过一个服务器程序,亏它还是服务器版本的,郁闷的我要死。目前为止的正常的服务器端网络程序都是在Windows下运行成功的,比如第一次那个daytime服务器,都是靠着移植到windows下才能成功,不过不停的调试啊,调试啊,gdb倒是熟悉了不少,还顺便熟悉了一堆的网络调试工具,linux下的netstat,tcpdump,windows下的Wireshark(linux因为没有X window,所以用不了)倒是真熟悉了很多,我都真不知道这样的死Ubuntu对于学习是好是坏了,假如没有碰到这么多问题的话,我不会调试一个那样简单的程序那么多次,不会这样的进一步熟悉那些特别简单的套接口API,真是,郁闷了。

中间发帖求救,有人说是防火墙,我配置了半天也没有反应,直接将ufw,iptables什么的都卸载了,结果还是不行!

最新的调试结果就是netstat显示的确服务器端listen成功了, tcpdump可以看到客户端的发送的SYN包,但是就是服务器不回ACK包,郁闷的客户端所以总是不停的发送几次SYN包,然后connect failed了,奇怪的家伙,我今晚准备下个ubuntu的普通版本试一下,服务器版本可能为了安全做了太多的手脚,我配置linux的能力又那么弱-_-!光学些bash,makefile什么的,对于配置文件的修改实在是不行,不然我也不会为了samba的配置郁闷到死,然后干脆传输文件都直接改用WinSCP,通过SSH传输,而不是通过共享了。唉。。。。。还是公司好,有管理员。

ubuntu普通版本还不行,我就只好换回FC了。。。。刚才看了一下已经到10了-_-!我上一次用的时候还是FC6呢,那时候4,5张盘,现在FC10只有1CD了,最近的操作系统瘦身工程进行的还挺彻底。要知道,连最最老的经典的RH9那时候都是4张盘。

呵呵,其实想起来,看的其实是UNIX的书,弄个真正的UNIX,比如FreeBSD什么的应该也挺不错的,可惜最近工作那个忙的啊。。。。都快吐血了,游戏快要上大规模的内测了,老总,总监催进度催的我一天头是大的,刚开始弄游戏的主逻辑服务器,第二天就要我设计并添加模块-_-!实在是@#%#$^@#$^$%@&$%基本上就那句话,不能上硬着头皮眯着眼睛也要上!唉。。。。所以嘛,还是暂时收收心吧。。。好好把网络编程学好都不错了,连Linux都没有弄转,呵呵,还是老实点好。

 

以下是我痛苦的调试经历:-_-!

@ubuntu:~$ netstat -a

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State

tcp        0      0 *:13000                 *:*                     LISTEN
@ubuntu:~$ netstat -a

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State

tcp        0      0 *:daytime                *:*                     LISTEN
@ubuntu:~$ netstat -a

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State

tcp        0      0 *:9877                  *:*                     LISTEN

三个不同的程序,都是卡在listen上。。。。

@ubuntu:~/test/testclient$ ./test 127.0.0.1
connet failed.
@ubuntu:~/test/testclient$ ./test 127.0.0.1
connet failed.

可怜的客户端啊。。。一次一次的connet failed

其实它实在不停的尝试的。。。。

一次:

@ubuntu:~$ sudo tcpdump port 9877
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
22:04:03.173472 IP 192.168.0.158.46269 > localhost.9877: S 1088742785:1088742785(0) win 5840 <mss 1460,sackOK,timestamp 95154 0,nop,wscale 4>
22:04:06.171580 IP 192.168.0.158.46269 > localhost.9877: S 1088742785:1088742785(0) win 5840 <mss 1460,sackOK,timestamp 95904 0,nop,wscale 4>

两次:

@ubuntu:~$ sudo tcpdump port 9877 -vv
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
22:05:09.022315 IP (tos 0x0, ttl 64, id 16507, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.46270 > localhost.9877: S, cksum 0xef4b (correct), 2110715003:2110715003(0) win 5840 <mss 1460,sackOK,timestamp 111616 0,nop,wscale 4>
22:05:12.019572 IP (tos 0x0, ttl 64, id 16508, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.46270 > localhost.9877: S, cksum 0xec5d (correct), 2110715003:2110715003(0) win 5840 <mss 1460,sackOK,timestamp 112366 0,nop,wscale 4>
22:05:18.019572 IP (tos 0x0, ttl 64, id 16509, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.46270 > localhost.9877: S, cksum 0xe681 (correct), 2110715003:2110715003(0) win 5840 <mss 1460,sackOK,timestamp 113866 0,nop,wscale 4>
22:05:30.019593 IP (tos 0x0, ttl 64, id 16510, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.46270 > localhost.9877: S, cksum 0xdac9 (correct), 2110715003:2110715003(0) win 5840 <mss 1460,sackOK,timestamp 116866 0,nop,wscale 4>
22:05:54.019575 IP (tos 0x0, ttl 64, id 16511, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.46270 > localhost.9877: S, cksum 0xc359 (correct), 2110715003:2110715003(0) win 5840 <mss 1460,sackOK,timestamp 122866 0,nop,wscale 4>
22:06:42.019581 IP (tos 0x0, ttl 64, id 16512, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.46270 > localhost.9877: S, cksum 0x9479 (correct), 2110715003:2110715003(0) win 5840 <mss 1460,sackOK,timestamp 134866 0,nop,wscale 4>
6 packets captured
6 packets received by filter
0 packets dropped by kernel

三次:

@ubuntu:~$ sudo tcpdump port 13000 -vv
[sudo] password for xqh:
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
22:44:49.480945 IP (tos 0x0, ttl 64, id 10118, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.60205 > localhost.13000: S, cksum 0xebc4 (correct), 793636653:793636653(0) win 5840 <mss 1460,sackOK,timestamp 706731 0,nop,wscale 4>
22:44:52.479579 IP (tos 0x0, ttl 64, id 10119, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.60205 > localhost.13000: S, cksum 0xe8d6 (correct), 793636653:793636653(0) win 5840 <mss 1460,sackOK,timestamp 707481 0,nop,wscale 4>
22:44:58.479574 IP (tos 0x0, ttl 64, id 10120, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.60205 > localhost.13000: S, cksum 0xe2fa (correct), 793636653:793636653(0) win 5840 <mss 1460,sackOK,timestamp 708981 0,nop,wscale 4>
22:45:10.479576 IP (tos 0x0, ttl 64, id 10121, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.60205 > localhost.13000: S, cksum 0xd742 (correct), 793636653:793636653(0) win 5840 <mss 1460,sackOK,timestamp 711981 0,nop,wscale 4>
22:45:34.479596 IP (tos 0x0, ttl 64, id 10122, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.60205 > localhost.13000: S, cksum 0xbfd2 (correct), 793636653:793636653(0) win 5840 <mss 1460,sackOK,timestamp 717981 0,nop,wscale 4>
22:46:22.479584 IP (tos 0x0, ttl 64, id 10123, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.60205 > localhost.13000: S, cksum 0x90f2 (correct), 793636653:793636653(0) win 5840 <mss 1460,sackOK,timestamp 729981 0,nop,wscale 4>
22:49:22.209124 IP (tos 0x0, ttl 64, id 2573, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.49879 > localhost.13000: S, cksum 0x20c8 (correct), 778754316:778754316(0) win 5840 <mss 1460,sackOK,timestamp 774913 0,nop,wscale 4>
22:49:25.207577 IP (tos 0x0, ttl 64, id 2574, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.49879 > localhost.13000: S, cksum 0x1dda (correct), 778754316:778754316(0) win 5840 <mss 1460,sackOK,timestamp 775663 0,nop,wscale 4>
22:49:31.207570 IP (tos 0x0, ttl 64, id 2575, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.49879 > localhost.13000: S, cksum 0x17fe (correct), 778754316:778754316(0) win 5840 <mss 1460,sackOK,timestamp 777163 0,nop,wscale 4>
22:49:43.207579 IP (tos 0x0, ttl 64, id 2576, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.49879 > localhost.13000: S, cksum 0x0c46 (correct), 778754316:778754316(0) win 5840 <mss 1460,sackOK,timestamp 780163 0,nop,wscale 4>
22:50:07.207588 IP (tos 0x0, ttl 64, id 2577, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.49879 > localhost.13000: S, cksum 0xf4d5 (correct), 778754316:778754316(0) win 5840 <mss 1460,sackOK,timestamp 786163 0,nop,wscale 4>
22:50:55.207580 IP (tos 0x0, ttl 64, id 2578, offset 0, flags [DF], proto TCP (6), length 60) 192.168.0.158.49879 > localhost.13000: S, cksum 0xc5f5 (correct), 778754316:778754316(0) win 5840 <mss 1460,sackOK,timestamp 798163 0,nop,wscale 4>

记住,就算我不改一个字,原《UNIX Network Programming》第一卷第三版一书的源程序(我试过4,5个前面几章的例子了),都是可以编译,可以运行,但是状况都是同样的。。。那就是connect不会成功。-_-!

处于对于原程序的一丝不信任,我自己重写了一些程序,但是几乎同样的程序,在Windows下相当的正常,但是在Ubuntu 8.04服务器版本上,还是同样的状况!!有没有人可以给我个解释啊。。。。。朝闻道夕死可矣。。。。。

 

举个例子,比如,linux下的两个程序:

服务器端:

 1 #include <stdio.h>  
 2 #include <stdlib.h>  
 3 #include <sys/socket.h>  
 4 #include <sys/time.h>  
 5 #include <time.h>  
 6 #include <netinet/in.h>  
 7 #include <errno.h>  
 8 #include <string.h>  
 9 #include <unistd.h>  
10   
11   
12 #define MAXLINE 1000  
13 **int**  main(**int**  argc, **char** * argv[])  
14 {  
15     **int**     listenfd, connfd;  
16     **struct**  sockaddr_in servaddr;  
17     //char buff[MAXLINE] = {0};  
18     //time_t   ticks;  
19   
20     listenfd = socket(AF_INET, SOCK_STREAM, 0);  
21     **if**(0 == listenfd)  
22     {  
23         printf("socket Error./n");  
24         **return**  -1;  
25     }  
26   
27     memset(&servaddr, 0, **sizeof**(servaddr));  
28     servaddr.sin_family      = AF_INET;  
29     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
30     servaddr.sin_port        = htons(13000);   /* daytime server */  
31   
32     **if**( 0 != bind(listenfd, (**struct**  sockaddr*)&servaddr, **sizeof**(servaddr)))  
33     {  
34         printf("bind error./n");  
35         close(listenfd);  
36         **return**  -1;  
37     }  
38   
39     **if**( 0 != listen(listenfd, 10))  
40     {  
41         printf("listen error./n");  
42         close(listenfd);  
43         **return**  -1;  
44     }  
45   
46     printf("listen right./n");  
47   
48     **char**  buffRecv[MAXLINE] = {0};  
49     connfd = accept(listenfd, (**struct**  sockaddr*)NULL, NULL);  
50           
51     printf("have accept./n");  
52   
53     **while**(true)  
54     {  
55         **int**  n = 0;  
56         **if**( 0 == (n = read(connfd, buffRecv, MAXLINE)) )  
57         {  
58             printf("recv failed/n");  
59             **break** ;  
60         }  
61         buffRecv[n] = 0;  
62         **if**( 0 == (n = write(connfd, buffRecv, strlen(buffRecv))) )  
63         {  
64             printf("send failed./n");  
65             **break** ;  
66         }  
67         fputs(buffRecv, stdout);  
68     }  
69     close(connfd);  
70     exit(0);  
71 }  
72

客户端:

 1 #include <stdio.h>  
 2 #include <stdlib.h>  
 3 #include <sys/socket.h>  
 4 #include <sys/time.h>  
 5 #include <time.h>  
 6 #include <netinet/in.h>  
 7 #include <errno.h>  
 8 #include <string.h>  
 9 #include <unistd.h>  
10 #include <arpa/inet.h>  
11   
12 #define MAXLINE 1000  
13   
14 **void**  str_cli(**FILE**  *fp, **int**  sockfd)  
15 {  
16     **char**  sendline[MAXLINE] = {0};  
17     **char**  recvline[MAXLINE] = {0};  
18     **while**  ( (fgets(sendline, MAXLINE, fp)) != NULL)   
19     {  
20   
21         **if**(0 == send(sockfd, sendline, strlen(sendline), 0))  
22         {  
23             printf("send failed./n");  
24             **break**  ;  
25         }  
26     }  
27     close(sockfd);  
28 }  
29   
30 **int**  main(**int**  argc, **char** * argv[])  
31 {  
32     **if**  (argc != 2)  
33     {  
34         printf("usage: tcpcli <IPaddress>");  
35         exit(1);  
36     }  
37   
38     **int**     sockfd = 0;  
39     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
40   
41     **struct**  sockaddr_in servaddr;  
42     memset(&servaddr, 0, **sizeof**(servaddr));  
43     servaddr.sin_family      = AF_INET;  
44     servaddr.sin_addr.s_addr = inet_addr(argv[1]);  
45     servaddr.sin_port        = htons(13000);   /* daytime server */  
46   
47     **if**( 0 != connect(sockfd, (**struct**  sockaddr *)&servaddr, **sizeof**(servaddr)))  
48     {  
49         printf("connet failed./n");  
50         close(sockfd);  
51         **return**  -1;  
52     }  
53   
54     str_cli(stdin, sockfd);        /* do it all */  
55     exit(0);  
56 }  
57

 

就这么简单的程序,硬是成功不了,何解?

几乎同样的程序,比如:

服务器端:

#include "Winsock2.h"

//#include "python.h"

//void CallPython(const char* apszPy)
//{
//  Py_Initialize();
//  PyRun_SimpleString(apszPy);
//  Py_Finalize();
//}

#define MAXLINE 1000

int main(int argc, char **argv)
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD( 2, 2 );

    // windows下此初始化为必须
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) {
       return -1;
    }

    SOCKET listenfd, connfd;
    struct sockaddr_in   servaddr;
    char   buff[MAXLINE];
    time_t ticks;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(INVALID_SOCKET == listenfd)
    {
       printf("socket Error: %d",WSAGetLastError());
       return -1;
    }

    ZeroMemory(&servaddr, sizeof(servaddr));
    servaddr.sin_family     = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(13);  /* daytime server */

    bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));

    listen(listenfd, SOMAXCONN);

    char   buffRecv[MAXLINE] = {0};
        
    connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
        
    while(true)
    {
       int n = 0;
       if( 0 == (n = recv(connfd, buffRecv, MAXLINE,0)) )
       {
           printf("recv failed, Error Code: %d", WSAGetLastError());
           break;
       }
       buffRecv[n] = 0;
//     CallPython(buffRecv);
       if( 0 == (n = send(connfd, buffRecv, strlen(buffRecv),0)) )
       {
           printf("send failed, Error Code: %d", WSAGetLastError());
           break;

       }

       fputs(buffRecv, stdout);
    }

    closesocket(connfd);
}

客户端:

#include "Winsock2.h"
#include "errno.h"
#include "stdlib.h"

#define MAXLINE 1000

void str_cli(FILE *fp, SOCKET sockfd)
{
    char sendline[MAXLINE] = {0};
    char recvline[MAXLINE] = {0};
    while ( (fgets(sendline, MAXLINE, fp)) != NULL) 
    {

       if(SOCKET_ERROR == send(sockfd, sendline, strlen(sendline), 0))
       {
           printf("send failed, Error Code: %d", WSAGetLastError());
           break ;
       }
    }
    closesocket(sockfd);
}
int main(int argc, char **argv)
{
    WORD wVersionRequested = 0;
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD( 2, 2 );

    // windows下此初始化为必须,实际包含加载WinsockDLL的过程
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) {
       return -1;
    }
    SOCKET               sockfd;
    struct sockaddr_in   servaddr;

    if (argc != 2)
    {
       printf("usage: tcpcli <IPaddress>");
       exit(1);
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    ZeroMemory(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if( SOCKET_ERROR == connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)))
    {
       printf("connet failed, Error Code: %d", WSAGetLastError());
       closesocket(sockfd);
       return -1;
    }

    str_cli(stdin, sockfd);     /* do it all */

    system("pause");
    exit(0);
}

 

就是运行的那么正常-_-!给我个解释?。。。。。另外,虽然做了写了好几个服务器了,我最近才知道。。原来。。。recv,send本来就是标准的套接口API。。。。我一直以为这些都是windows扩展的-_-!《Unix Network Programming》书以前只看了前面一点,因为前面用的都是read,write接口来写套接字,所以嘛。。。呵呵,误解了,以前还常喊windows下用的recv,send很奇怪呢-_-!太无知了,所以嘛,还是要好好学习底层知识才行。。。不能太依赖于公司的网络框架了,虽然那个框架写的真是不赖。。。好用的很。。。

有在Ubuntu 8.04版本上成功accept的兄弟,请告知怎么样配置的。。。。

 

以此纪念刚开始在linux上学习网络编程的失败-_-!

 

 

write by九天雁翎(JTianLing) – www.jtianling.com

分类:  网络技术 
标签:  C++ 

Posted By 九天雁翎 at 九天雁翎的博客 on 2009年02月17日

前一篇: 为C++的map翻案,map实际是排序并且迭代效率不低的 后一篇: 学习网络编程ubuntu桌面版比服务器版更好?