ShareIdeas

本博客不再更新,欢迎访问我的github,https://github.com/sunke-github/

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  学习一段时间的linux下的程序编写,着手开发环境的搭建如:安装 arm-linux-gcc交叉编译环境,tftp服务器,smb服务,vncserver服务,nfs服务.深入学习了C语言编程,以及linux进程线程相关方面的知识.见于后期会用到linux的网络传输,这里先着手linux下网络通信方面程序的编写 .

  花了几天的时间终于把linux下 TCP 的通信程序简单写了写,包括 tcp_client.c  和 tcp_server.c  。tcp_client.c 负责发送字符串,tcp_server.c 负责接收。代码如下,程序很简单,和网上的大同小异,但做了修改和优化,代码如下:

tcp_server.c

 1 #include <stdlib.h> 
 2 #include <stdio.h> 
 3 #include <errno.h> 
 4 #include <string.h> 
 5 #include <netdb.h> 
 6 #include <sys/types.h> 
 7 #include <netinet/in.h> 
 8 #include <sys/socket.h> 
 9 
10 #define portnumber 8500 
11 
12 int main(int argc, char *argv[]) 
13 { 
14     int sockfd,new_fd; 
15     struct sockaddr_in server_addr; 
16     struct sockaddr_in client_addr; 
17     int sin_size; 
18     int nbytes;
19     char buffer[1024];
20     
21 
22     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:IPV4;SOCK_STREAM:TCP
23     { 
24         fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); 
25         exit(1); 
26     } 
27 
28     bzero(&server_addr,sizeof(struct sockaddr_in)); // 初始化,置0
29     server_addr.sin_family=AF_INET;                 // Internet
30     server_addr.sin_addr.s_addr=htonl(INADDR_ANY);  
31     server_addr.sin_port=htons(portnumber);         
32     
33     if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) 
34     { 
35         fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); 
36         exit(1); 
37     } 
38 
39     if(listen(sockfd,5)==-1) 
40     { 
41         fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); 
42         exit(1); 
43     } 
44           
45 
46     printf("start listen...\n");
47     while(1) 
48     { 
49         
50         sin_size=sizeof(struct sockaddr_in);// This is must be in while()?
51         printf("waiting for connection ----\n");
52         if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) 
53         { 
54             fprintf(stderr,"Accept error:%s\n\a",strerror(errno)); 
55             exit(1); 
56         } 
57         fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); 
58         while(1)
59         {
60             //if((nbytes=read(new_fd,buffer,1024))==-1) 
61             nbytes=read(new_fd,buffer,1024);
62               
63                 if((nbytes==0)||(nbytes==-1))
64                  {
65                 if(nbytes==0)
66                 {
67                     printf("The connection is error !\n");
68                     printf("restart server !\n");
69                     break;
70                 }
71                 else
72                     fprintf(stderr,"Read Error:%s\n",strerror(errno)); 
73                 exit(1); 
74              }
75                  
76             buffer[nbytes]='\0';
77             printf("Server received %i--%s\n",nbytes,buffer);
78         
79             //close(new_fd);
80             printf("continute... !\n");
81             /* 循环下一个 */
82         } 
83     } 
84 
85     close(sockfd);   //How to jump here ? 
86     printf("Close socket !\n");
87     exit(0); 
88 }
89     

tcp_client.c

 1 #include <stdlib.h> 
 2 #include <stdio.h> 
 3 #include <errno.h> 
 4 #include <string.h> 
 5 #include <netdb.h> 
 6 #include <sys/types.h> 
 7 #include <netinet/in.h> 
 8 #include <sys/socket.h> 
 9 #include <time.h>
10 #define portnumber 8500 
11 
12 int main(int argc, char *argv[]) 
13 { 
14     int sockfd;
15     int nbytes; 
16     char buffer[1024]; 
17     struct sockaddr_in server_addr; 
18     struct hostent *host; 
19 
20 
21     if(argc!=2) 
22     { 
23         fprintf(stderr,"Usage:%s hostname \a\n",argv[0]); 
24         exit(1); 
25     } 
26 
27     if((host=gethostbyname(argv[1]))==NULL) 
28     { 
29         fprintf(stderr,"Gethostname error\n"); 
30         exit(1); 
31     } 
32 
33 
34     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:Internet;SOCK_STREAM:TCP
35     { 
36         fprintf(stderr,"Socket Error:%s\a\n",strerror(errno)); 
37         exit(1); 
38     } 
39 
40 
41     bzero(&server_addr,sizeof(server_addr)); // 初始化,置0
42     server_addr.sin_family=AF_INET;          // IPV4
43     server_addr.sin_port=htons(portnumber);  // (将本机器上的short数据转化为网络上的short数据)端口号
44     server_addr.sin_addr=*((struct in_addr *)host->h_addr); // IP地址
45     
46 
47     if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) 
48     { 
49         fprintf(stderr,"Connect Error:%s\a\n",strerror(errno)); 
50         exit(1); 
51     } 
52 
53 
54     printf("Please input char:\n");
55     while(1)
56     {
57         //string ->  char *
58         strcpy(buffer,"Test string to char..");
59         nbytes=write(sockfd,buffer,strlen(buffer));
60     
61         printf("Write string Test string to char..\n"); 
62         sleep(1);
63     }
64 
65 
66     /* 结束通讯 */ 
67     close(sockfd); 
68     exit(0); 
69 } 

为了方便程序的调试,简单写了个Makefile文件

  1 all:tcp_server tcp_client
  2 tcp_server:tcp_server.c
  3         gcc -g tcp_server.c -o tcp_server
  4 tcp_client:tcp_client.c
  5         gcc -g tcp_client.c -o tcp_client

程序简单介绍, 本程序是面向连建的TCP 通讯程序, 其中 read() 方法是阻塞读, 当连接发生异常时 返回值是 0.所以我在tcp_server.c程序里加了个判断,用以判断连接情况。有时间把本程序改成多线程的。我在程序编写的过程中遇到了printf()无输出的情况,查了一下“因为就算执行printf后只是将内容送到缓冲区,但是你到程序结束里,程序结束便会导致缓冲区刷新,你便看到你到屏幕上有你期望到东西出现了。所以我最 后得到一个这样到结论:printf会把东西送到缓冲区,而如果缓冲区不刷新到话,你便不会在屏幕上看到东西,而能导致缓冲区刷新到情况有这些:1 强制刷新 fflush;2,放到缓冲区到内容中包含\n \r ;3,缓冲区已满;4,需要从缓冲区拿东西到时候,如执行scanf”   。

2013.7.30 日 ,花了一些时间把 网络通信程序修改成了多线程网络通信程序,多线程的好处是:一个线程的阻塞可以不影响主线程的执行.

简单包括一些互斥量的创建好使用,和线程的创建

 /*----initialize the mutex---------------*/
 89         pthread_mutex_init(&mutex_r,NULL);
 90         /*------ create the read thread -------- */
 91         ret = pthread_create(&id1, NULL, (void*)read_pthread, NULL);
 92         if (ret)
 93         {
 94                 printf("Create pthread error!\n");
 95                 return -1;
 96         }
 97         printf("start the read_pthread successefully !\n");

和线程存活的判断

         if(pthread_kill(id1,0)!=0)
105         {
106                 printf("read_pthread is stoped .\n");
107                 /*--must stop the write pthread ----*/
108                 return -1;
109         }

具体便不再赘述.目前已经实现了C#四轴操作端和 arm9 开发板的多线程网络通信:

操作过程 : 启动linux 端程序,等待TCP连接--> C#操控端连接手柄-->设置网络地址 -->启动通信 --> linux 端成功接收数据.

博文为本人所写,转载请表明出处, 博客园 :梦工厂2012  Linux 网络编程

posted on 2013-06-16 10:06  ShareIdeas  阅读(258)  评论(0编辑  收藏  举报