一、创建TCP 服务器流程图

二、创建 TCP 客户端流程图

三、搭建服务器和客户端间双向交流模型
#include <my_head.h>
typedef struct pack
{
int size;
char buf[4096];
int used;
}pack_t;
//将数据添加到数据包
void pack_append_data(pack_t* pack,const char* val)
{
//buf前两个字节用于存储数据字节大小
char *buf=pack->buf;
//计算传输数据长度
short len = strlen(val);
//buf的前两个字节存储数据长度
*(short *)(buf+pack->used) = len;
pack->used += 2;
//buf前两个字节用于存储数据字节大小
//将字符串存储在buf的后续内存中
strcpy(buf+pack->used,val);
pack->used += len ;
pack->size = 4 + pack->used;
}
//采用指针数组解包数据
char** read_data_from_pack(pack_t* pack)
{
//定义字符针,指向pack中的buf
char* buf = pack->buf;
//定义指针数组,并在堆区为其申请空间
char** data = (char**)calloc(20,sizeof(char*));
if(NULL == data)
{
printf("指针数组堆区空间申请失败\n");
}
//对data数组进行清零
bzero(data,20*sizeof(char*));
//定义标记位
//记录已读取数据字节大小
int read_size = 0;
int i = 0;
while(read_size < pack->size -8)
{
//前两个字节用于记录数据字节大小,不取
short size = *(short*)(buf + read_size);
read_size += 2;
if(size<=0 || read_size + size >pack->size-4)
{
printf("无效数据长度\n");
return NULL ;
}
//定义字符数组用于接收数据
char temp[size+1];
memset(temp,0,size+1);
//将数据拷贝到temp数组中
strncpy(temp,buf+read_size,size);
//read_size增加temp的长度
read_size += strlen(temp);
//重新为指针数组中的每个指针申请堆区空间
//之前申请的堆区空间大小为指针的固定字节大小
data[i] = (char *)calloc(1,size+1);
//将temp数组中数据拷贝到data[i]中
strcpy(data[i],temp);
//i自增
i++;
}
return data;
}
void receive_message(int port);
void send_message(int port);
int main(int argc, const char *argv[])
{
if(argc<2)
{
printf("请输入端口号\n");
return -1;
}
short port = atoi(argv[1]);
int flag;
printf("请输入要进行的操作:\n");
printf("1.接收消息\n");
printf("2.发送消息\n");
scanf("%d",&flag);
switch(flag)
{
case 1:
receive_message(port);
break;
case 2:
send_message(port);
break;
default:
printf("输入错误\n");
break;
}
}
//接收消息
void receive_message(int port)
{
//创建服务器
int sever = socket(AF_INET,SOCK_STREAM,0);
if(-1==sever)
{
perror("socket failed");
return ;
}
struct sockaddr_in addr = {0};
addr.sin_family=AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("0.0.0.0"); // 绑定到所有接口
if(-1==bind(sever,(struct sockaddr *)&addr,sizeof(addr)))
{
perror("bind error");
close(sever);
return ;
}
listen(sever,10); //监控服务器
struct sockaddr_in client_addr; //定义客户端结构体
int client_len=sizeof(client_addr); //获取客户端结构体字节大小
int client = accept(sever,(struct sockaddr*)&client_addr,&client_len);
//调用accpet 函数接收客户端发送的数据
if(-1==client)
{
perror("accept failed");
close(sever);
return ;
}
printf("有客户端连接\n");
//接收数据包
while(1)
{
int size = 0;
int res = read(client,&size,4);
printf("res = %d\n",size);
if(0 == res)
{
printf("客户端断开连接\n");
close(sever);
return ;
}
pack_t pack = {0}; //定义数据包,用于接收数据
pack.size = size;
res = read(client,(char *)&pack+4,size-4);
printf("pack.buf=[%s]\n",pack.buf);
//将客户端中的账号和密码数据存储在pack后续的内存中,其大小为size-4
//调用解包函数,输出数据
char** data = read_data_from_pack(&pack);
printf("接收到消息:\n");
}
close(sever);
return;
}
//发送消息
void send_message(int port)
{
//创建客户端
int client = socket(AF_INET,SOCK_STREAM,0);
if(-1==client)
{
perror("socket failed");
return ;
}
struct sockaddr_in addr = {0};
addr.sin_family=AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("192.168.141.46");
connect(client,(struct sockaddr*)&addr,sizeof(addr));
//发送数据包
char message[128];
while(1)
{
memset(message,0,sizeof(message)); //数据清零
printf("请输入消息:\n");
scanf("%s",message);
getchar(); //吸收换行符
pack_t pack = {0};
pack_append_data(&pack,message);
write(client,&pack,pack.size);
}
close(client);
return ;
}