本文只是總結一下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;
- }
- }
- }
#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);
- }
#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);
}
以上即完成了簡單的udp程序。另一個tcp程序在此處下載。同樣比較簡單,不解釋!
在文章後面說一下大小端(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");
- }
- }
#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