Sock Demo 增加结构体的定义和传输

先来声明下本项目的设计目标吧。项目由已工作的师兄从自己现在所在项目组的任务简化抽象而来。

设计一个基于Socket或基于HTTP的服务器,服务内容是提供一种简单的key/value映射关系的管理与查询
下面的所有操作都是通过结构体Node来传递的:
struct Node {
    char key[KEY_SIZE];
    char value[VALUE_SIZE];
};

本场景中需要client和server两个程序。
client:
client端只有两种操作:
int AddNode(const struct Node *node); // 将指定的node保存到server上,需要key和value都完整
int GetNode(struct Node *node); // 输入的node需要有完整的key,server负责将这个key对应的value填到node中,或返回不存在。
server:
server端就是接收client的两种请求,然后要么保存node要么查询node并返回值。


以下代码将再上文基础上加入结构体的定义,实现AddNode和GetNode两个功能(为封装为函数,抱歉日后修正),并在server端加入对两种情况的响应。

server.c

#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"messageStruct.h"

#define MAXLINE 4096

int main(int argc, char** argv)
{
    int    listenfd, connfd;
    struct sockaddr_in     servaddr;
    char    buff[4096];
    int     n;
	MSG info; //定义结构体变量

    /*协议域:AF_INET ipv4地址(32位的)与端口号(16位的)的组合
    SOCK_STREAM提供面向连接的稳定数据传输,即TCP协议。
    参数protocol用来指定socket所使用的传输协议编号。这一参数通常不具体设置,一般设置为0即可。
    */
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
    printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
     /*
    INADDR_ANY绑定默认的网卡ip,
    htonl其实是host to network, l 的意思是返回类型是long,将主机的无符号长整形数转换成网络字节顺序。
    */
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(6666);//将一个无符号短整形数从网络字节顺序转换为主机字节顺序。

    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
    printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    if( listen(listenfd, 10) == -1){
    printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    printf("======waiting for client's request======\n");
    while(1){
		if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1)
		{
		    printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
		    continue;
		}
		n = recv(connfd, buff, MAXLINE, 0);    
		memset(&info,0,sizeof(info));
		memcpy(&info,buff,sizeof(info));
		printf("recv msg from client:\nkey:%s\nvalue:%s\n", info.key,info.value);
		if(info.value[0]=='\n')
		{
			memcpy(&info.value,"value",sizeof(info.value));
			memcpy(buff,&info,sizeof(info));
			if( send(connfd, buff, sizeof(buff), 0) < 0)
			{
				printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
				exit(0);
			}
		}
		close(connfd);
    }
    close(listenfd);
}


client.c

#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"messageStruct.h"

#define MAXLINE 4096

int main(int argc, char** argv)
{
    int    sockfd, n;
    char    recvline[4096], sendline[4096];
    struct sockaddr_in    servaddr;
	MSG info; //定义结构体变量

    if( argc != 2){
    printf("usage: ./client <ipaddress>\n");
    exit(0);
    }

    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
    exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(6666);
	//inet_pton(int af, const char *src, void *dst); Linux下IP地址转换函数,可以在将IP地址在“点分十进制”和“整数”之间转换
    if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
    printf("inet_pton error for %s\n",argv[1]);
    exit(0);
    }

    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
    printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

	printf("Please input the key string:\n");
	memset(info.key,0,sizeof(info.key));
	fgets(info.key, 4096, stdin);
	printf("Please input the value string, if you'd like to get the value of a key, keep it blank\n");
	memset(info.value,0,sizeof(info.value));
	fgets(info.value, 4096, stdin);
	memset(sendline,0,4096);//清空发送缓存,不清空的话可能导致接收时产生乱码,
	memcpy(sendline,&info,sizeof(info)); //结构体转换成字符串
	
	if( send(sockfd, sendline, sizeof(sendline), 0) < 0)
    {
    	printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
    	exit(0);
    }
	if(info.value[0]=='\n')
	{		
		memset(recvline,0,4096);
    	n = recv(sockfd, recvline, MAXLINE, 0);    
		memset(&info,0,sizeof(info));
		memcpy(&info,recvline,sizeof(info));
    	printf("recv msg from client:\nkey:%s\nvalue:%s\n", info.key,info.value);
	}

    close(sockfd);
    exit(0);
}

messageStruct.h

#define KEY_SIZE 1024
#define VALUE_SIZE 1024
typedef struct Node {
   	 	char key[KEY_SIZE];
   	 	char value[VALUE_SIZE];
	}MSG;


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值