C/Linux网络编程VI——UDP客户端和服务器端通信模型

程序一

服务器端仅仅打印从客户端受到的字符串。客户端仅仅发一次字符串给服务器端。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_PORT 9527 

//used to throw out an error
void sys_err(const char *str){
	perror(str);
	exit(1);
}
int main(){
	int sfd = socket(PF_INET,SOCK_DGRAM,0);
//设定用户端的套接字地址
	struct sockaddr_in serv_addr;//server socket address
		serv_addr.sin_family = PF_INET;
		serv_addr.sin_port = htons(SERV_PORT);
		serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//这个用来存储客户端的套接字信息,暂时是不知道的
	struct sockaddr_in clnt_addr;//client socket address
	socklen_t lgth_clnt_addr = sizeof(clnt_addr);
//缓冲
	int rec = 0;
	char buf[BUFSIZ];
//一些判断
	if(sfd == -1){
		sys_err("fail to create a socket!");
	}
	if((bind(sfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))) == -1){
		sys_err("fail to bind a socket!");
	}
//服务器真正执行的功能
	while(1){
		//wait until the arrival of any udp datagram
		while((rec = recvfrom(sfd,(void *)buf,BUFSIZ,0,(struct sockaddr *)&clnt_addr,&lgth_clnt_addr)) == 0){
//这个函数的用处是接受从客户端来的数据,并且取得客户端的套接字地址。rec为-1时表明接收失败,0和正整数表明接受到的字符数目。sfd为服务器端某socket的文件描述符,buf是用于存放接受的字符串的数组,BUFSIZ是sizeof(buf),0这里是个形参flag(设成0就好),(struct sockaddr*)&clnt_addr是一个传出参数(别忘了前面的强制类型转换)存储客户端套接字的地址,&lgth_clnt_addr也是传出参数存放客户端套接字地址的长度。
		}
		//if any message, print it in the screen
		write(STDOUT_FILENO,buf,rec);
	}
	
//关闭套接字
	close(sfd);
	return 0;	
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_PORT 9527
void sys_err(const char *str){
        perror(str);
        exit(1);
}
int main(){
        int cfd = socket(PF_INET,SOCK_DGRAM,0);
        struct sockaddr_in serv_addr;
                serv_addr.sin_family = PF_INET;
                serv_addr.sin_port = htons(SERV_PORT);
                inet_pton(PF_INET,"127.0.0.1",&serv_addr.sin_addr.s_addr);
        if(cfd == -1){
                sys_err("fail to create a socket!");
        }
        // there is no need to bind for cfd --- it's automatic
        char buf[] = "have fun!\n";
/*sendto函数用于向指定地址的套接字发送字符串。返回值-1表示失败,0或正整数表示发送的字符的数量。
cfd是客户端的某一socket的文件描述符,buf是所传输的字符串,sizeof(buf)是所传输的字符串的长度
serv_addr是接收方的套接字地址(勿忘强转),sizeof(serv_addr)为接收方套接字地址的长度(由于不是传出参数,所以和recvfrom的最后一个参数不同,不是指针),那个0是形参flag。*/
        sendto(cfd,buf,sizeof(buf),0,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
        return 0;
}

程序二 

在程序一的基础上进行修改,将其改为实现echo功能的UDP通信程序。(即客户端向服务器端发送一个字符,服务器接收这个字符后将其发给客户端)。

程序三

这是作业的要求。

 客户端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
void sys_err(const char *str){
        perror(str);
        exit(1);
}
double pow(double x,double y){
        double result = 1;
        int i = 1;
        for(i = 1;i <= y;++i){
                result *= x;
        }
        return result;
}
//used to transform numbers in string format into short format
short toShort(char *str,int length){
        double number = 0;
        int i = 1;
        for(i = 1;i <= length;++i){
                number = number + (str[i-1] - '0') * pow(10,length - i);
        }
        return  (short) number;
}
int main( int argc, char *argv[]){
        //test for pow and toShort
/*      char v[] = "9527";
        printf("%lf\n",pow(2,3));
        printf("%d\n",toShort(v,sizeof(v) - 1));
*/
        //argument number check argv[0]:filename, argv[1]:server IP 
        //argv[2]:server port    argv[>=3]: data 
        // at least three arguments needed
        if(argc < 3){
                sys_err("UDPlab_c.out wants at least three arguments!");
        }
        if(argc >= 3){
                //firstly, print the server address
                puts("----------------------------------------------------");
                printf("UDP server: <ip> =  %s ;<port> = %s\n",argv[1],argv[2]);
        }
        //network function      
        char* ipaddr = argv[1];
        short port = toShort(argv[2],sizeof(argv[2] - 1));
        int cfd = socket(PF_INET,SOCK_DGRAM,0);
        struct sockaddr_in serv_addr;
                serv_addr.sin_family = PF_INET;
                serv_addr.sin_port = htons(port);
                inet_pton(PF_INET,ipaddr,&serv_addr.sin_addr.s_addr);
        if(cfd == -1){
                sys_err("fail to create a socket!");
        }
        // there is no need to bind for cfd --- it's automatic

        //the real function of the client
        char **stringArray = argv;
        int i = 3;
        for(i=3;i < argc;++i){
                sendto(cfd,*(stringArray + i),sizeof(stringArray[i]),0,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
//              printf("%s\n",*(stringArray + i));
        }
        return 0;

 服务器端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_PORT 9527 
//used to joint two strings
char *strjoint(char* str1,int ls1,char* str2,int ls2){
        //str1 as the input-output arguments, so it must have enough space
        int i = 0;
        for(i = ls1;;++i){
                if(str2[i - ls1] == '\0'){
                        str1[i] = '\0';
                        break;
                }
                else{
                        str1[i] = str2[i - ls1];
                }
        }
        return str1;
}

//used to throw out an error
void sys_err(const char *str){
        perror(str);
        exit(1);
}
int main(){
        int sfd = socket(PF_INET,SOCK_DGRAM,0);
        struct sockaddr_in serv_addr;//server socket address
                serv_addr.sin_family = PF_INET;
                serv_addr.sin_port = htons(SERV_PORT);
                serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        struct sockaddr_in clnt_addr;//client socket address
        socklen_t lgth_clnt_addr = sizeof(clnt_addr);
        int rec = 0;
        char buf[BUFSIZ];
        if(sfd == -1){
                sys_err("fail to create a socket!");
        }
        if((bind(sfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))) == -1){
                sys_err("fail to bind a socket!");
        }
/*//test for strjoit
char s1[] = "have"; char s2[] = " fun!";
printf("%s\n",strjoint(s1,sizeof(s1) - 1,s2,sizeof(s2) - 1));
*/

        //the server real function
        puts("./UDPserver: wait for data on port 9527");
        while(1){
                //wait until the arrival of any udp datagram
                while((rec = recvfrom(sfd,(void *)buf,BUFSIZ,0,(struct sockaddr *)&clnt_addr,&lgth_clnt_addr)) == 0){

                }
        char ip[30]; inet_ntop(PF_INET,&clnt_addr.sin_addr.s_addr,ip,30);
        printf("./UDPserver: ");
        printf("from client <ip> = %s ",ip);
        printf("<port> = %d",ntohs(clnt_addr.sin_port));
        printf(" <content> = %s\n",buf);
//      write(STDOUT_FILENO,buf,rec);
        }

        close(sfd);
        return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值