以下有一個簡單的透過UDP來傳送訊息的程式,udp與tcp的差別在於tcp不能由server連續傳訊息給client而必需client-server-client間接傳。
而udp就可以由server連續傳訊息給client
udpserver.c
//==============================include file==========================
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
//====================================================================
//==============================define variable=======================
#define MAXLINE 80
#define SERV_PORT 8888
//====================================================================
//==============================define function=======================
void do_echo(int sockfd,struct sockaddr *pcliaddr,socklen_t clilen);
//====================================================================
//=============================main function==========================
int main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in servaddr,cliaddr;
// create a socket, using the UDP
sockfd = socket(AF_INET,SOCK_DGRAM,0);
// init servaddr
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=INADDR_ANY;
servaddr.sin_port=htons(SERV_PORT);
// bind address and port to socket
if (bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))==-1)
{
perror("bind error,the ip address is wrong");
exit(1);
}
do_echo(sockfd,(struct sockaddr*)&cliaddr,sizeof(cliaddr));
return 0;
}
//====================================================================
//==============================function implement====================
void do_echo(int sockfd,struct sockaddr *pcliaddr,socklen_t clilen)
{
int n;
socklen_t len;
char mesg[MAXLINE];
for (;;)
{
len=clilen;
// wait for receive data
n = recvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,&len);
// sent data back to client
sendto(sockfd,mesg,n,0,pcliaddr,len);
}
}
//====================================================================
udpclient.c
//=============================include file================================
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
//=========================================================================
//=============================define variable=============================
#define MAXLINE 80
#define SERV_PORT 8888
//=========================================================================
//=============================define function=============================
void do_cli(FILE *fp,int sockfd,struct sockaddr *pservaddr,socklen_t servlen);
//=========================================================================
//=============================main function===============================
int main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
char error_message[20];
// check args
if (argc!=2)
{
printf("usage:udpclient <IP address>\n");
exit(1);
}
// init servaddr
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(SERV_PORT);
if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0)
{
sprintf(error_message,"[%s] is not a valid IP address\n",argv[1]);
fputs(error_message,stderr);
exit(1);
}
// build the socket, using the UDP
sockfd=socket(AF_INET,SOCK_DGRAM,0);
do_cli(stdin,sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
return 0;
}
//=========================================================================
//=============================function implement==========================
void do_cli(FILE *fp,int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
{
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
// connect to server
if (connect(sockfd,pservaddr,servlen)==-1)
{
perror("connect error");
exit(1);
}
while (fgets(sendline,MAXLINE,fp)!=NULL)
{
// read a line and send to server
write(sockfd,sendline,strlen(sendline));
// receive data from server
n=read(sockfd,recvline,MAXLINE);
if (n==-1)
{
perror("read error");
exit(1);
}
// terminate string
// 依字串的最後面加上一個結束符號
recvline[n]=0;
fputs(recvline,stdout);
}
}
//=========================================================================
有用到的新的東西:
void * memset ( void * ptr, int value, size_t num );
把ptr指標指到的地方,用value的值填滿num個
參考
host to network short
uint16_t htons(uint16_t hostshort);
htons函數用來轉換u_short了來自主機的TCP / IP網絡字節順序(即big-endian )的.
參數hostshort [ ] 16位元數的主機字節順序.
返回值的htons函數返回值的TCP / IP網路字元順序.
須知htons函數有一個16位號碼主機字元順序並返回一個16位數字網路字元
參考
參考2
參考3
htons-htons的功能
FILE * stdin
等待使用者輸入字串,並回傳FILE的指標,與scanf比起來,scanf會以「空白」當作分隔
但是,透過char * fgets ( char * str, int num, stdin );
會把使用者輸入的字串存放到str的指標中,且長度必需小於num-1,如此一來不會以「空白」當作中斷
當我們輸入"good"時,實際上存到str的會是"good\n",也就是在最後面加上一個結束符號。
這裡要注意的是它自動加入的是null
A null character is automatically appended in str after the characters read to signal the end of the C string.
但是非常奇怪的就是用strlen(str)會比原來的長度還要加1,所以,我猜測最後加入的不是'\0'而是'\n',所以,長度才會比原本的多一
這裡就要提到,若使用char *gets( char *str )
不會在最後加入一個結束符號。
FILE *stdout
可以把字串傳送到螢幕上
透過int fputs ( const char * str, stdout);
可以把str指標指到的字串送到螢幕上
FILE *stderr
可以把字串送到錯誤串流
透過int fputs(const char *str,stderr);
可以把str指標指到的字串送到螢幕上
void perror ( const char * str );
perror()用來將上一個函數發生錯誤的原因輸出到標準錯誤(stderr)。參數s所指的字串會先印出,後面再加上錯誤原因字串。此錯誤原因依照全局變量errno的值來決定要輸出的字符串。
若上一個函數沒有執行失敗的話,那就會出現
"訊息":SUCCESS
參考
參考2
參考3
參考4
參考5
上面的一些函數後面都不能加變數,因此可能必需與
int sprintf ( char * str, const char * format, ... );
一起使用。先把所有的變數一起轉成字串,再把字串傳給上面幾個函數使用
參考
int fprintf ( FILE * stream, const char * format, ... );
把字串輸入到檔案中
fprintf(stderr,"there are some errors:%s",string);
回傳值是寫入多少字元
參考資料:
recvfrom
練習 Socket UDP 通訊實驗
socket編程原理
STDIN
編寫Linux下的UDP Client/Server程序
[转]总述基金选择的步骤
16 年前
沒有留言:
張貼留言