学习一段时间的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 网络编程