利用C语言实现在客户端和服务器端发送一个整数

来源:互联网 发布:建筑公司法务 知乎 编辑:程序博客网 时间:2024/05/21 21:45

    tcp的特性就是面向字节流,就是发送的内容必须是字节!如果要发送一个整数的话,由于整数可能是多个字节,所以就需要拆分成多个字节发送,然后发送到服务器端再来进行合并!我这里的实现代码如下:

客户端的代码:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<signal.h>#define SIZE 4096int main(int argc,char *argv[]){    int sockfd;    struct sockaddr_in servaddr;    char buf_r[SIZE];    char buf_s[SIZE];    memset(&servaddr,0,sizeof(servaddr));    memset(buf_s,0,SIZE);    memset(buf_r,0,SIZE);    if(argc != 2)    {printf("Usage:%s <Server IP address>\n",argv[0]+2);exit(EXIT_FAILURE);    }    if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)//socket第三个参数0表示根据定义的域和类型来自动选择协议    {printf("%s[socket]%s",argv[0]+2,strerror(errno));exit(EXIT_FAILURE);    }    //给套接字地址结构赋值,用来保存服务器的地址    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(9877);    inet_pton(AF_INET,argv[1],(struct in_addr *)&servaddr.sin_addr);    //客户端向服务器发起连接请求    if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1)    {printf("%s[connect]%s",argv[0]+2,strerror(errno));exit(EXIT_FAILURE);    }//********************************************************************************************************//    //这里进行数据的处理    int num,loop,count;    char c;    printf("请输入一个整数:");    while(0 == scanf("%d",&num))    {while((c=getchar()) != EOF);  //将缓冲区的内容清空printf("对不起,您输入的数据有误,请重新输入!\n");printf("请输入一个整数:");    }    count = (int)(sizeof(int)/sizeof(char));    for(loop=0;loop<count;loop++)    {buf_s[loop] = (char)(num >> (loop*sizeof(char)*8));    }    printf("Sent:");    for(loop=0;loop<count;loop++)printf("%hhX ",buf_s[count-loop-1]);    printf("\n");    write(sockfd,buf_s,strlen(buf_s));    if(read(sockfd,buf_r,SIZE) == 0)    {printf("服务器已经关闭了连接!\n");return -1;    }    else    {printf("Receive:");for(loop=0;loop<count;loop++)    printf("%hhX ",buf_r[count-loop-1]);printf("\n");    }    return 0;}
服务器端的代码:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<netinet/in.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>#include<unistd.h>#define SIZE 4096#define CON_SIZE 1024int main(int argc,char *argv[]){    int listenfd,cli_sockfd;    struct sockaddr_in servaddr,cliaddr;    char buf[SIZE];    //接受缓存    socklen_t len;    //接受的客户端的地址结构的长度    char cli_ip[SIZE];    //客户端的IP地址    memset(buf,0,SIZE);/**********************************************************************************************************/    //1.创建监听套接字    if(-1 == (listenfd=socket(AF_INET,SOCK_STREAM,0))) //这里的0表示根据定义的域和协议类型来自动选择协议!    {printf("%s[socket]:%s\n",argv[0]+2,strerror(errno));exit(EXIT_FAILURE);    }/**********************************************************************************************************/    //2.给服务器地址结构赋值    memset(&servaddr,0,sizeof(struct sockaddr_in));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(9877);    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/**********************************************************************************************************/    //3.设置套接字选项,让套接字关闭后地址没有等待时间,能够立刻进行绑定    int on = 1;    if(-1 == setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))    {printf("%s[setsockopt]:%s\n",argv[0]+2,strerror(errno));exit(EXIT_FAILURE);    }/**********************************************************************************************************/    //4.将服务器地址结构和监听套接字绑定    if(-1 == bind(listenfd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in)))    {printf("%s[bind]:%s\n",argv[0]+2,strerror(errno));exit(EXIT_FAILURE);    }/**********************************************************************************************************/    //5.进行监听    if(-1 == listen(listenfd,CON_SIZE))    {printf("%s[listen]:%s\n",argv[0]+2,strerror(errno));exit(EXIT_FAILURE);    }    while(1)    {/**********************************************************************************************************///6.接受连接请求if(-1 == (cli_sockfd=accept(listenfd,(struct sockaddr*)&cliaddr,&len))){    printf("%s[accept]:%s\n",argv[0]+2,strerror(errno));    exit(EXIT_FAILURE);}if(NULL == inet_ntop(AF_INET,&cliaddr.sin_addr,cli_ip,SIZE))  //保存发送端的IP地址{    printf("%s[inet_ntop]:%s\n",argv[0]+2,strerror(errno));    exit(EXIT_FAILURE);}ntohs(cliaddr.sin_port);//保存发送端的端口号printf("[%s:%d]连接已建立\n",cli_ip,cliaddr.sin_port);/**********************************************************************************************************///7.接受并回传数据int loop;int num,num_temp;if(-1 == read(cli_sockfd,buf,SIZE)){    printf("%s[read]:%s\n",argv[0]+2,strerror(errno));    exit(EXIT_FAILURE);}for(loop=0;loop<4;loop++){    num_temp = (int)buf[4-loop-1];    num_temp = num_temp << ((4-loop-1)*8);    switch(4-loop-1)    {    case 0:num_temp = num_temp | 0xFFFFFF00;num = num & num_temp;break;    case 1:num_temp = num_temp | 0xFFFF00FF;num = num & num_temp;break;    case 2:num_temp = num_temp | 0xFF00FFFF;num = num & num_temp;break;    case 3:num_temp = num_temp | 0x00FFFFFF;num = num_temp;break;    }    printf("%hhX ",buf[4-loop-1]);}printf("\n");printf("发送过来的数是:%d\n",num);if(-1 == write(cli_sockfd,buf,strlen(buf))){    printf("%s[write]:%s\n",argv[0]+2,strerror(errno));    exit(EXIT_FAILURE);}/**********************************************************************************************************///8.关闭套接字if(-1 == close(cli_sockfd)){    printf("%s[close]:%s\n",argv[0]+2,strerror(errno));    exit(EXIT_FAILURE);}else{    printf("[%s:%d]创建的套接字已经关闭\n",cli_ip,cliaddr.sin_port);    memset(buf,0,SIZE);}    }    return 0;}


这个程序实现的比较简单,就是客户端发送一个整数给服务器端,然后服务器端显示这个整数是多少,再把这个字节流回传给客户端!运行结果如下图:




程序的不足之处:

    1.整数的长度问题:

        我这里用的是int类型,在客户端可以通过sizeof获取到要发送到整数的长度,但是在服务器端我还没想好怎样来传送整数的长度比较好,所以直接用了一个4!并没有实现判断整数到底是多少个字节!

    2.字节序问题:

        在不同的主机上,可能是大端字节序或者是小端字节序,我这里并没有做处理,因为我这里是用127.0.0.1来实验的,都是在我的电脑上,所以字节序是相同的!我这里不知道的是如何获取一个一个主机的字节序,所以这里还没做!

0 0
原创粉丝点击