本文只是总结一下linux下tcp与udp程序的编写,其实不管平台如何,简单的tcp与udp程序的结构还是不会变的。如下所示:
tcp(基于链接)的简单程序结构
udp(无连接)的程序结构
过程不在赘述,看看一个基于上面过程的简单udp代码:
udpserver.c
#include<stdlib.h> #include<stdio.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netdb.h> #define PORT 8900 int main() { int sockfd; struct sockaddr_in server; struct sockaddr_in client; char send_buf[2048]; char recv_buf[2048]; int length; int sendnum; int recvnum; int port; port = PORT; int opt = SO_REUSEADDR; /*The first stage:initnial phase*/ /*1.1 generating socket phrahse*/ if (-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0))) { perror("error in generate socket\n"); exit(1); } #ifdef DEBUG printf("the sokcet id is %d\n",sockfd); printf("enter binding phrase....\n"); #endif setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); /*1.2 binding the socket*/ memset(&server,0,sizeof(struct sockaddr)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(port); if (-1==bind(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr))) { perror("error in binding phrase\n"); close(sockfd); exit(1); } #ifdef DEBUG printf("leaving binding phrase\n"); printf("entering data exchange phrase\n"); #endif length = sizeof(struct sockaddr_in); /* The Second Stage: data exchange phrase */ while(1) { memset(&send_buf,0,sizeof(send_buf)); memset(&recv_buf,0,sizeof(recv_buf)); /* receive the data from the client*/ recvnum=recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&client,&length); recv_buf[recvnum]='\0'; printf("the message from the client is %s:\n",recv_buf); sendnum = sprintf(send_buf,"hello,the guest from %s",inet_ntoa(client.sin_addr)); sendto(sockfd,send_buf,sendnum,0,(struct sockaddr*)&client,sizeof(struct sockaddr)); if (0==strcmp(recv_buf,"quit")) { perror("the server is terminted by client\n"); close(sockfd); return 0; } } }
udpclient.c
#include<stdlib.h> #include<stdio.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netdb.h> void print_usage(char* str) { printf("the command %s usage is:\n",str); printf("%s Ip_Address [port] \n"); } int main(int argc,char**argv) { int sockfd; struct sockaddr_in server; struct sockaddr_in reply; char send_buf[2048]; char recv_buf[2048]; int length; int sendnum; int recvnum; int port; port = atoi(argv[2]); if ((2>argc) ||(argc>3)) { print_usage(argv[0]); exit(1); } /*The first stage:initnial phase*/ /*1.1 generating socket phrahse*/ if (-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0))) { perror("error in generate socket\n"); exit(1); } #ifdef DEBUG printf("the sokcet id is %d\n",sockfd); printf("enter data exchange phrase....\n"); #endif /*1.2 setting the destinate address */ memset(&server,0,sizeof(struct sockaddr)); server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(argv[1]); server.sin_port = htons(port); /* The Second Stage: data exchange phrase */ memset(&send_buf,0,sizeof(send_buf)); memset(&recv_buf,0,sizeof(recv_buf)); printf("what words do you want to tell to server:\n"); gets(send_buf); /* send the data to the server*/ sendnum = strlen(send_buf); if(0>sendto(sockfd,send_buf,sendnum,0,(struct sockaddr*)&server,sizeof(struct sockaddr))) { perror("send data error\n"); close(sockfd); exit(0); } recvnum = recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr *)&server,&length); if (0>recvnum) { perror("receive data error\n"); close(sockfd); exit(0); } recv_buf[recvnum]='\0'; printf("the message from the server is :%s\n",recv_buf); close(sockfd); exit(0); }
在文章后面说一下大小端(big endian于little endian)的问题吧,相信大家都知道大小端到底使什么东西,这里也不多说,现在要提到的是如何如何编程实现判断所用机器是大端机器还是小端机器。我们知道,在C语言中,union中的字段是“共享内存”的,在一个union结构中,它的大小取决于其字段中最大的那个并且与之相等。其实想到这儿相信大家都已经知道了怎么来判断机器的大小端了,没错,就是使用union类型的特点进行判断。现在就基于C中的union写一个判断机器是大小端的程序。如下:
#include<stdio.h> union Nate { unsigned short s; char cs[2]; }nate; void main() { nate.s = 1; printf("nate.s is : %x\n",nate.s); printf("nate.cs[0] is : %d\n",nate.cs[0]); printf("nate.cs[1] is : %d\n",nate.cs[1]); if(nate.cs[0] == 1) { printf("little endian!\n"); } else if(nate.cs[0] == 0) { printf("big endian!\n"); } }
在gcc中编译运行程序即可看到本机器是大端还是小端了!这可以说是使用C中union的特性的一个好的应用,对于理解C中union类型也不错!
文中包含程序在此处可以下载:http://download.csdn.net/detail/Natepan/3636259