题目
代码
服务器
typedef char DataType[32]; //普通节点数据类型
typedef struct NODE
{
union
{
DataType data; //普通节点数据域
int len; //头节点数据域
};
struct NODE *next; //指针域
}node,*nodePtr;
struct PACK
{
int size; //告知 通信传输的数据的大小
int type; //决定对数据如何操作
char buf[1500]; //数据
int count; //用于记录 已经 读取/写入 到数据的什么位置
};
//创建头节点
nodePtr creatList(void);
//申请节点 封装数据
nodePtr malloc_newnode(DataType e);
//添加数据
void add_data(nodePtr H,DataType e);
//解析数
nodePtr unlood(nodePtr H,struct PACK packPtr);
//显示数据
void showdata(nodePtr H);
int main(int argc, const char *argv[])
{
//创建套接字
int serverfd=socket(AF_INET,SOCK_STREAM,0); //ipv4 tcp形式 自动选择协议
//ip地址 和 potr端口号 放入"网络通信结构体"
struct sockaddr_in addr;
addr.sin_family=AF_INET; //ipv4
int port=atoi(argv[1]);
addr.sin_port=htons(port); //端口号 (大端存储)
addr.sin_addr.s_addr=inet_addr("0.0.0.0"); //ip地址
//结构体数据 写入 套接字
int res=bind(serverfd,(struct sockaddr*)&addr,sizeof(addr));
if(res==-1)
{
printf("套接字 创建失败\n");
perror("bind");
return 0;
}
printf("套接字 创建成功\n");
//监听
listen(serverfd,10);
//接受链接
struct sockaddr_in client_addr; //创建"网络信息结构体" 用于接受客户端消息
int client_addr_len=sizeof(client_addr); //长度
int clientfd=accept(serverfd,(struct sockaddr *)&client_addr,&client_addr_len);
printf("链接到客户端\n");
nodePtr H=creatList(); //创建头节点
if(NULL==H){return 0;}
//读取数据
while(1)
{
//创建 网络通信结构体
struct PACK pack;
pack.count=0; //读写位置 初始化为0
int res=read(clientfd,&pack.size,4);
if(res==0){break;}
res=read(clientfd,(char *)&pack+4,pack.size-4);
if(res==0){break;}
//解析数据
unlood(H,pack);
//显示数据
showdata(H);
}
return 0;
}
nodePtr creatList(void)
{
nodePtr H=(nodePtr)malloc(sizeof(node));
if(NULL==H)
{
printf("节点申请失败\n");
return NULL;
}
//头节点 指针域处理
H->next=NULL;
//头节点 数据域处理
H->len=0;
return H;
}
//申请节点 封装数据
nodePtr malloc_newnode(DataType e)
{
nodePtr newnode=(nodePtr)malloc(sizeof(node));
if(NULL==newnode)
{
printf("节点申请失败\n");
return NULL;
}
//指针域 处理
newnode->next=NULL;
//数据域 处理
memcpy(newnode->data,e,sizeof(DataType));
return newnode;
}
void add_data(nodePtr H,DataType e)
{
nodePtr newnode=malloc_newnode(e);
if(NULL==newnode)
{
printf("普通节点申请失败 或 数据放入链表失败\n");
return;
}
nodePtr temp=H;
while(temp->next!=NULL)
{
temp=temp->next; //成为下一个节点
}
//最后一个节点 指向本节点
temp->next=newnode;
//链表长度增加
H->len++;
}
nodePtr unlood(nodePtr H,struct PACK packPtr)
{
if(NULL==H)
{
printf("地址不合法");
return NULL;
}
while(1)
{
//获取数据长度
int len=*(short *)(packPtr.buf+packPtr.count);
if(len==0)
{
printf("数据解析完毕\n\n");
return H;
}
packPtr.count+=2;
//读取字符串数据 写入到buf
DataType e={0};
memcpy(e,packPtr.buf+packPtr.count,len);
add_data(H,e);
packPtr.count+=len;
}
}
void showdata(nodePtr H)
{
if(NULL==H)
{
printf("链表地址不合法\n");
return;
}
if(H->len==0)
{
printf("链表数据为空\n");
return;
}
nodePtr temp=H;
while(temp->next!=NULL)
{
temp=temp->next; //成为下一个节点
printf("data=%s\n",temp->data); //输出显示数据
}
printf("链表数据 显示完毕\n");
}
客户端
struct PACK
{
int size; //数据包大小
int type; //对数据的操作
char buf[1500]; //数据
int conut; //数据已经占用多少字节
};
//数据附加 放入数据
void append(struct PACK* pack,const char *data);
int main(int argc, const char *argv[])
{
//创建套接字
int clientfd=socket(AF_INET,SOCK_STREAM,0); //ipv4 tcp形式 自动选择协议
//ip地址 和 potr端口号 放入"网络通信结构体"
struct sockaddr_in addr;
addr.sin_family=AF_INET; //ipv4
int port=atoi(argv[1]);
addr.sin_port=htons(port); //端口号
addr.sin_addr.s_addr=inet_addr("192.168.93.128"); //服务器ip地址
//结构体数据 写入 套接字
int res=connect(clientfd,(struct sockaddr*)&addr,sizeof(addr));
if(res==-1)
{
printf("套接字 创建失败\n");
perror("bind");
return 0;
}
//发送
struct PACK pack;
pack.conut=0;
while(1)
{
char buf[20];
printf("请输入 用户:");
scanf("%19s",buf);
while(getchar()!=10);
append(&pack,buf);
printf("请输入 密码:");
scanf("%19s",buf);
while(getchar()!=10);
append(&pack,buf);
pack.size=pack.conut+8; //包实际大小
write(clientfd,&pack,pack.size); //发送给服务器 将接受多少字节
pack.conut=0; //发送完毕 conut 重置
}
return 0;
}
//数据附加 放入数据
void append(struct PACK* pack,const char *data)
{
int len=strlen(data);
*(short *)(pack->buf+pack->conut)=len;
pack->conut+=2;
memcpy(pack->buf+pack->conut,data,len);
pack->conut+=len;
}
效果