Chinaunix首页 | 论坛 | 博客
  • 博客访问: 106252
  • 博文数量: 33
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 188
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-23 19:19
文章分类

全部博文(33)

文章存档

2015年(22)

2014年(11)

我的朋友

分类: C/C++

2015-01-09 20:08:38


1 示例一 摘自《深入Linux内核架构》

echo_server.c

[html] view plaincopy
  1. #include<stdio.h>  
  2. #include<netinet/in.h>  
  3. #include<sys/types.h>  
  4. #include<string.h>  
  5. <span style="color:#ff0000;">#include <arpa/inet.h>  
  6. span>int main() {  
  7.     char* echo_host = "10.239.142.209";  
  8.     int echo_port = 7777;  
  9.     int sockfd;  
  10.     struct sockaddr_in *server=  
  11.     (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));  
  12.   
  13.     /* Set own address */  
  14.     server->sin_family = AF_INET;  
  15.     server->sin_port = htons(echo_port);  
  16.   
  17.     // Note network byte order!  
  18.     server->sin_addr.s_addr = inet_addr(echo_host);  
  19.   
  20.     /* Create a socket */  
  21.     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  22.   
  23.     /* Bind to an address */  
  24.     if (bind(sockfd, (struct sockaddr*)server, sizeof(*server))) {  
  25.         printf("bind failed\n");  
  26.     }  
  27.   
  28.     /* Enable server mode of socket */  
  29.     listen(sockfd, SOMAXCONN);  
  30.   
  31.     /* ...and wait for incoming data */  
  32.     int clientfd;  
  33.     struct sockaddr_in* client =  
  34.     (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));  
  35.     int client_size = sizeof(*client);  
  36.     char* buf = (char*)malloc(1000);  
  37.     int bytes;  
  38.     printf("Wait for connection to port %u\n", echo_port);  
  39.   
  40.     /* Accept a connection request */  
  41.     clientfd = accept(sockfd, (struct sockaddr*)client, &client_size);  
  42.     printf("Connected to %s:%u\n\n", inet_ntoa(client->sin_addr), ntohs(client->sin_port));  
  43.     printf("Numeric: %u\n", ntohl(client->sin_addr.s_addr));  
  44.   
  45.     while(1) {  
  46.         /* Endless loop */  
  47.         /* Receive transmitted data */  
  48.         bytes = read(clientfd, (void*)buf, 1000);  
  49.         if (bytes <= 0) {  
  50.             close(clientfd);  
  51.             printf("Connection closed.\n");  
  52.             exit(0);  
  53.         }  
  54.         printf("Bytes received: %u\n", bytes);  
  55.         printf("Text: ’%s’\n", buf);  
  56.   
  57.         /* Send response */  
  58.         write(clientfd, buf, bytes);  
  59.     }  
  60. }  
echo_client.c



[html] view plaincopy
  1. #include<stdio.h>  
  2. #include<netinet/in.h>  
  3. #include<sys/types.h>  
  4. #include<string.h>  
  5.   
  6. int main() {  
  7.     /* Host and port number of the echo server */  
  8.     char* echo_host = "10.239.142.209";  
  9.     int echo_port = 7777;  
  10.     int sockfd;  
  11.   
  12.     struct sockaddr_in *server=  
  13.     (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));  
  14.   
  15.     /* Set address of server to be connected */  
  16.     server->sin_family = AF_INET;  
  17.     server->sin_port = htons(echo_port);  
  18.   
  19.     // Note network byte order!  
  20.     server->sin_addr.s_addr = inet_addr(echo_host);  
  21.   
  22.     /* Create a socket (Internet address family, stream socket and  
  23.     default protocol) */  
  24.     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  25.   
  26.     /* Connect to server */  
  27.     printf("Connecting to %s \n", echo_host);  
  28.     printf("Numeric: %u\n", server->sin_addr);  
  29.     connect(sockfd, (struct sockaddr*)server, sizeof(*server));  
  30.   
  31.     /* Send message */  
  32.     char* msg = "Hello World";  
  33.     printf("\nSend: ’%s’\n", msg);  
  34.     write(sockfd, msg, strlen(msg));  
  35.   
  36.     /* ... and receive result */  
  37.     char* buf = (char*)malloc(1000); // Receive buffer for max. 1000 chars  
  38.     int bytes = read(sockfd, (void*)buf, 1000);  
  39.     printf("\nBytes received: %u\n", bytes);  
  40.     printf("Text: ’%s’\n", buf);  
  41.   
  42.     /* End communication (i.e. close socket) */  
  43.     close(sockfd);  
  44. }  


2 示例二:来源于网络

server.c


[html] view plaincopy
  1. /* server.c */  
  2.   
  3. #include <stdio.h>  
  4.   
  5. #include <stdlib.h>  
  6.   
  7. #include <errno.h>  
  8.   
  9. #include <string.h>  
  10.   
  11. #include <sys/types.h>  
  12.   
  13. #include <netinet/in.h>  
  14.   
  15. #include <sys/socket.h>  
  16.   
  17. #include <sys/wait.h>  
  18.   
  19. <span style="color:#ff6666;">#include <arpa/inet.h>  
  20. span>  
  21.   
  22. void showClientInf(struct sockaddr_in client_addr) {  
  23.   
  24.         printf("\nThe IP of client is:%s",inet_ntoa(client_addr.sin_addr));  
  25.   
  26.         printf("\nThe Port of client is:%d\n",ntohs(client_addr.sin_port));  
  27.   
  28. }  
  29.   
  30.   
  31.   
  32. int main() {  
  33.   
  34.     int sockfd,new_fd;  
  35.   
  36.     struct sockaddr_in my_addr;  
  37.   
  38.     struct sockaddr_in their_addr;  
  39.   
  40.     int sin_size;  
  41.   
  42.     char buff[100];  
  43.   
  44.     int numbytes;  
  45.   
  46.   
  47.   
  48.     printf("socket\n");  
  49.     if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1) {  
  50.   
  51.         perror("socket");  
  52.   
  53.         exit(1);  
  54.   
  55.     }  
  56.   
  57.   
  58.   
  59.     my_addr.sin_family = AF_INET;  
  60.   
  61.     my_addr.sin_port = htons(2323);  
  62.   
  63.     my_addr.sin_addr.s_addr = INADDR_ANY;  
  64.   
  65.     bzero(&(my_addr.sin_zero),8);  
  66.   
  67.   
  68.     printf("bind\n");  
  69.   
  70.     if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)  
  71.   
  72.     {  
  73.   
  74.         perror("bind");  
  75.   
  76.         exit(1);  
  77.   
  78.     }  
  79.   
  80.   
  81.     printf("listen\n");  
  82.   
  83.     if(listen(sockfd,10)==-1) {  
  84.   
  85.         perror("listen");  
  86.   
  87.         exit(1);  
  88.   
  89.     }  
  90.   
  91.     printf("server is run...\n");  
  92.   
  93.   
  94.   
  95.     while(1) {  
  96.   
  97.         sin_size = sizeof(struct sockaddr_in);  
  98.   
  99.   
  100.         printf("accept\n");  
  101.   
  102.         if((new_fd = accept(sockfd,(struct sockaddr *)  
  103.   
  104.         &their_addr,&sin_size))==-1)  
  105.   
  106.         {  
  107.   
  108.             perror("accept");  
  109.   
  110.             exit(1);  
  111.   
  112.         }  
  113.   
  114.   
  115.   
  116.         showClientInf(their_addr);  
  117.   
  118.   
  119.   
  120.         if(!fork()) {  
  121.   
  122.             printf("recv\n");  
  123.   
  124.             if((numbytes = recv(new_fd,buff,sizeof(buff),0))==-1)  
  125.   
  126.             {  
  127.   
  128.                 perror("recv");  
  129.   
  130.                 exit(1);  
  131.   
  132.             }  
  133.   
  134.             buff[numbytes]='\0';  
  135.   
  136.             printf("recieved %d bytes.\n",numbytes);  
  137.   
  138.             printf("the message is:%s\n",buff);  
  139.   
  140.             printf("send\n");  
  141.   
  142.             if(send(new_fd,buff,strlen(buff),0)==-1)  
  143.   
  144.                 perror("send");  
  145.   
  146.             printf("close-new_fd 1\n");  
  147.   
  148.             close(new_fd);  
  149.   
  150.             exit(0);  
  151.   
  152.         }  
  153.         printf("close-new_fd 2\n");  
  154.   
  155.         close(new_fd);  
  156.   
  157.     }  
  158.     printf("close-sockfd\n");  
  159.   
  160.     close(sockfd);  
  161.   
  162. }  

client.c



[html] view plaincopy
  1. /* client.c */  
  2.   
  3. #include <stdio.h>  
  4.   
  5. #include <stdlib.h>  
  6.   
  7. #include <errno.h>  
  8.   
  9. #include <string.h>  
  10.   
  11. #include <netdb.h>  
  12.   
  13. #include <sys/types.h>  
  14.   
  15. #include <netinet/in.h>  
  16.   
  17. #include <sys/socket.h>  
  18. <span style="color:#ff0000;">#include <arpa/inet.h>  
  19. span>  
  20.   
  21. int main(int argc,char *argv[]) {  
  22.   
  23.     int sockfd,numbytes;  
  24.   
  25.     char buf[100];  
  26.   
  27.     //char *msg="hello world";  
  28.     char *msg;  
  29.   
  30.     struct hostent *he;  
  31.   
  32.     struct sockaddr_in their_addr;  
  33.   
  34.     int i = 0;  
  35.   
  36.   
  37.   
  38.   
  39.     if(argc<3) {  
  40.   
  41.         printf("You should input IP and message!\n");  
  42.   
  43.         exit(1);  
  44.   
  45.     }  
  46.   
  47.     he = gethostbyname(argv[1]);  
  48.     msg = argv[2];  
  49.   
  50.   
  51.     printf("he->h_addr=%s, msg=%s\n", inet_ntoa(*(struct in_addr *)he->h_addr), msg);  
  52.   
  53.     printf("socket\n");  
  54.   
  55.     if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1) {  
  56.   
  57.     perror("socket");  
  58.   
  59.     exit(1);  
  60.   
  61.     }  
  62.   
  63.   
  64.   
  65.   
  66.     their_addr.sin_family = AF_INET;  
  67.   
  68.     their_addr.sin_port = htons(2323);  
  69.   
  70.     their_addr.sin_addr = *((struct in_addr *)he->h_addr);  
  71.   
  72.     bzero(&(their_addr.sin_zero),8);  
  73.   
  74.   
  75.     printf("connect\n");  
  76.   
  77.     if(connect(sockfd,(struct sockaddr *)&their_addr,  
  78.   
  79.     sizeof(struct sockaddr))==-1){  
  80.   
  81.     perror("connect");  
  82.   
  83.     exit(1);  
  84.   
  85.     }  
  86.   
  87.   
  88.     printf("send\n");  
  89.   
  90.     if(send(sockfd,msg,strlen(msg),0)==-1) {  
  91.   
  92.     perror("send");  
  93.   
  94.     exit(1);  
  95.   
  96.     }  
  97.   
  98.   
  99.     printf("recv\n");  
  100.   
  101.     if((numbytes = recv(sockfd,buf,100,0))==-1) {  
  102.   
  103.     perror("recv");  
  104.   
  105.     exit(1);  
  106.   
  107.     }  
  108.   
  109.     buf[numbytes] = '\0';  
  110.   
  111.     printf("result:%s",buf);  
  112.     printf("close\n");  
  113.   
  114.     close(sockfd);  
  115.   
  116.     return 0;  
  117.   
  118. }  

3 解决的问题

初始代码在执行的时候,到inet_ntoa都会出现Segmentation fault,加上#include 就正常可以使用了。这是因为使用的Ubuntu是64位,32位的系统不存在这个问题。《深入Linux内核架构》里面的示例还存在Server/Client端口号不一致的情况。真不知道是怎么验证的。


4 使用GDB来观察执行流程

如果只要编译可执行文件,一下命令即可:

gcc -o server server.c

gcc -o client client.c

但如果要用GDB来Debug,就需要带上Debug信息了:

gcc  -g server.c -o server

gcc -g client.c -o client


5 附上常用GDB命令解释


Linux中包含有一个很有用的调试工具--gdb(GNU Debuger),它可以用来调试C和C++程序,功能不亚于Windows下的许多图形界面的调试工具。

和所有常用的调试工具一样,gdb提供了以下功能:
 # 监视程序中变量的值
 # 在程序中设置断点
 # 程序的单步执行

在使用gdb前,必须先载入可执行文件,因为要进行调试,文件中就必须包含调试信息,所以在用gcc或cc编译时就需要用-g参数来打开程序的调试选项。

调试开始时,必须先载入要进行调试的程序,可以用以下两种方式:
 * 在启动gdb后执行以下命令:
   file 可执行文件路径
 * 在gdb启动时就载入程序:
   gdb 可执行文件路径

载入程序后,接下来就是要进行断点的设置,要监视的变量的添加等工作,下面对在这个过程中常会用到的命令逐一进行介绍:
 * list:显示程序中的代码,常用使用格式有:
    list
      输出从上次调用list命令开始往后的10行程序代码。
    list -
      输出从上次调用list命令开始往前的10行程序代码。
    list n
      输出第n行附近的10行程序代码。
    list function
      输出函数function前后的10行程序代码。
 * forward/search:从当前行向后查找匹配某个字符串的程序行。使用格式:
    forward/search 字符串
  查找到的行号将保存在$_变量中,可以用print $_命令来查看。
 * reverse-search:和forward/search相反,向前查找字符串。使用格式同上。
 * break:在程序中设置断点,当程序运行到指定行上时,会暂停执行。使用格式:
    break 要设置断点的行号
 * tbreak:设置临时断点,在设置之后只起作用一次。使用格式:
    tbreak 要设置临时断点的行号
 * clear:和break相反,clear用于清除断点。使用格式:
    clear 要清除的断点所在的行号
 * run:启动程序,在run后面带上参数可以传递给正在调试的程序。
 * awatch:用来增加一个观察点(add watch),使用格式:
    awatch 变量或表达式
  当表达式的值发生改变或表达式的值被读取时,程序就会停止运行。
 * watch:与awatch类似用来设置观察点,但程序只有当表达式的值发生改变时才会停止运行。使用格 式:
    watch 变量或表达式
  需要注意的是,awatch和watch都必须在程序运行的过程中设置观察点,即可运行run之后才能设置。
 * commands:设置在遇到断点后执行特定的指令。使用格式有:
    commands
      设置遇到最后一个遇到的断点时要执行的命令
    commands n
      设置遇到断点号n时要执行的命令
  注意,commands后面跟的是断点号,而不是断点所在的行号。
  在输入命令后,就可以输入遇到断点后要执行的命令,每行一条命令,在输入最后一条命令后输入end就可以结束输入。
 * delete:清除断点或自动显示的表达式。使用格式:
    delete 断点号
 * disable:让指定断点失效。使用格式:
    disable 断点号列表
  断点号之间用空格间隔开。
 * enable:和disable相反,恢复失效的断点。使用格式:
    enable 断点编号列表
 * ignore:忽略断点。使用格式:
    ignore 断点号 忽略次数
 * condition:设置断点在一定条件下才能生效。使用格式:
    condition 断点号 条件表达式
 * cont/continue:使程序在暂停在断点之后继续运行。使用格式:
    cont
      跳过当前断点继续运行。
    cont n
      跳过n次断点,继续运行。
  当n为1时,cont 1即为cont。
 * jump:让程序跳到指定行开始调试。使用格式:
    jump 行号
 * next:继续执行语句,但是跳过子程序的调用。使用格式:
    next
      执行一条语句
    next n
      执行n条语句
 * nexti:单步执行语句,但和next不同的是,它会跟踪到子程序的内部,但不打印出子程序内部的语句。使用格式同上。
 * step:与next类似,但是它会跟踪到子程序的内部,而且会显示子程序内部的执行情况。使用格式同上。
 * stepi:与step类似,但是比step更详细,是nexti和step的结合。使用格式同上。
 * whatis:显示某个变量或表达式的数据类型。使用格式:
    whatis 变量或表达式
 * ptype:和whatis类似,用于显示数据类型,但是它还可以显示typedef定义的类型等。使用格式:
    ptype 变量或表达式
 * set:设置程序中变量的值。使用格式:
    set 变量=表达式
    set 变量:=表达式
 * display:增加要显示值的表达式。使用格式:
    display 表达式
 * info display:显示当前所有的要显示值的表达式。
 * delete display/undisplay:删除要显示值的表达式。使用格式:
    delete display/undisplay 表达式编号
 * disable display:暂时不显示一个要表达式的值。使用格式:
    disable display 表达式编号
 * enable display:与disable display相反,使用表达式恢复显示。使用格式:
    enable display 表达式编号
 * print:打印变量或表达式的值。使用格式:
    print 变量或表达式
  表达式中有两个符号有特殊含义:$和$$。
  $表示给定序号的前一个序号,$$表示给定序号的前两个序号。
  如果$和$$后面不带数字,则给定序号为当前序号。
 * backtrace:打印指定个数的栈帧(stack frame)。使用格式:
    backtrace 栈帧个数
 * frame:打印栈帧。使用格式:
    frame 栈帧号
 * info frame:显示当前栈帧的详细信息。
 * select-frame:选择栈帧,选择后可以用info frame来显示栈帧信息。使用格式:
    select-frame 栈帧号
 * kill:结束当前程序的调试。
 * quit:退出gdb。

如要查看所有的gdb命令,可以在gdb下键入两次Tab(制表符),运行“help command”可以查看命令command的详细使用格式。

来源:http://blog.csdn.net/arnoldlu/article/details/9701553

PS:以上两个示例都在Ubuntu10.10 64bit上验证过。

以上两则示例源码下载地址:

阅读(1223) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~