TLV头文件
#ifndef __TLV_H__
#define __TLV_H__
//发送命令的类型(获取文件列表还是指定文件)
enum type_t{
FLIST = 0,
FGET
};
enum send_status_t{
SEND_FHEAD = 1,
SEND_FBODY,
SEND_FOVER
};
//发送数据的命令头结构
typedef struct{
unsigned char type;
unsigned long len;
}cmd_head_t;
//发送的文件头部信息
typedef struct{
char fname[256];
unsigned long flen;
}file_head_t;
enum is_start_t{
START = 0,
STOP
};
typedef struct
{
int sock_fd;
int file_fd;
int is_start;
int send_status;
}client_info_t;
#endif
服务器示例
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "tlv.h"
#define MAX_SIZE 512
int send_data(int sockfd, char *data, int len)
{
int recv_len = 0;
int total_len = 0;
while (total_len < len){
recv_len = send(sockfd, data + total_len, len - total_len, 0);
if (recv_len < 0){
if (errno == EAGAIN || errno == EINTR){
usleep(1000);
continue;
}
return -1;
}
total_len += recv_len;
}
return 0;
}
int recv_data(int sockfd, char *data, int len)
{
int count = 0;
int recv_len = 0;
while (recv_len < len){
recv_len = recv(sockfd, data, len, 0);
if (errno == EAGAIN || errno == EINTR){
if (count++ > 5){
printf("count error\n");
return -1;
}
usleep(1000);
continue;
}
}
return recv_len;
}
int main(int argc, char *argv[])
{
int sockfd;
int ret;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int client_sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
perror("socket error");
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9000);
server_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
int opt = 1;
if(setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, (const void *)&opt, sizeof(opt))){
perror("setsockopt");
return -1;
}
int len = sizeof(struct sockaddr_in);
ret = bind(sockfd, (struct sockaddr*)&server_addr, len);
if (ret == -1){
perror("bind error");
return -1;
}
ret = listen(sockfd, MAX_SIZE);
if (ret < 0){
return -1;
}
char buff[MAX_SIZE] = {0};
char filename[256] ={0};
file_head_t fh;
int flag;
int opret = -1;
while (1){
client_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &len);
if (client_sockfd < 0){
continue;
}
printf("new client--ip:[%s], port:[%d]\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
while (1){
memset(buff, 0x00,MAX_SIZE);
memset(filename, 0x00,256);
memset(&fh, 0x00, sizeof(file_head_t));
int recv_len = recv_data(client_sockfd, (char*)&flag, sizeof(int));
if (((int)flag) == SEND_FHEAD){
recv_len = recv_data(client_sockfd, (char *)&fh, sizeof(file_head_t));
printf("file name:[%s], size:[%ld]\n", fh.fname, fh.flen);
sprintf(filename, "../%s", fh.fname);
opret = open(filename , O_CREAT | O_RDWR | O_TRUNC | O_APPEND, 0666);
if (opret < -1){
perror("open error");
return -1;
}
}else if (((int)flag) == SEND_FBODY){
recv_len = recv_data(client_sockfd, buff, MAX_SIZE);
}else if (((int)flag) == SEND_FOVER){
break;
}
//printf("recv_len = %d\n", recv_len);
if (recv_len == MAX_SIZE){
//printf("recv buff:%s\n", buff);
write(opret, buff, strlen(buff));
}
}
close(client_sockfd);
}
close(opret);
close(sockfd);
return 0;
}
客户端示例
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "tlv.h"
#define MAX_SIZE 512
int recv_data(int sockfd, char *data, int len)
{
int recv_len = 0;
int count = 0;
while (recv_len < len){
recv_len = recv(sockfd, data, len, 0);
if (errno == EAGAIN || errno == EINTR){
if (count++ > 5){
return -1;
}
usleep(1000);
continue;
}
if (recv_len != len){
return -1;
}
}
return 0;
}
int send_data(int sockfd, char *data, int len)
{
int recv_len = 0;
int total_len = 0;
while (total_len < len){
recv_len = send(sockfd, data + total_len, len - total_len, 0);
printf("send_data recv_len = %d\n", recv_len);
if (recv_len < 0){
if (errno == EAGAIN || errno == EINTR){
usleep(1000);
continue;
}
return -1;
}
total_len += recv_len;
}
return total_len;
}
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int ret;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
perror("socket error");
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9000);
server_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(8000);
client_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
int opt = 1;
if(setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, (const void *)&opt, sizeof(opt))){
perror("setsockopt");
return -1;
}
int len = sizeof(struct sockaddr_in);
ret = bind(sockfd, (struct sockaddr*)&client_addr, len);
if (ret == -1){
perror("bind error");
return -1;
}
ret = connect(sockfd, (struct sockaddr*)&server_addr, len);
if (ret < 0){
perror("connect error");
return -1;
}
int opret;
//打开要发送的文件
if ((opret = open("./hehe.txt", O_RDONLY)) < 0){
perror("open error");
return -1;
}
//设置客户端信息
client_info_t *pci;
pci = (client_info_t *)malloc(sizeof(client_info_t));
pci->sock_fd = sockfd;
pci->file_fd = opret;
pci->send_status = SEND_FHEAD; //发送文件头信息
file_head_t fh;
memset(&fh, 0x00, sizeof(file_head_t));
memcpy(fh.fname, "hehe.txt", strlen("hehe.txt"));
fh.flen = strlen("hehe.txt");
int send_len = MAX_SIZE;
char buff[MAX_SIZE] = {0};
int i = 0, s_len;
while (1){
memset(buff, 0x00, MAX_SIZE);
if (pci->send_status == SEND_FHEAD){
printf("send file head\n");
//告诉服务器即将发送文件头信息
send_data(pci->sock_fd, (char *)&pci->send_status, sizeof(pci->send_status));
//开始发送文件头信息
send_data(pci->sock_fd, (char *)&fh, sizeof(file_head_t));
//修改发送状态为发送文件数据
pci->send_status = SEND_FBODY;
}else if (pci->send_status == SEND_FBODY){
printf("send file data\n");
//告诉服务器即将发送文件数据
send_data(pci->sock_fd, (char*)&pci->send_status, sizeof(pci->send_status));
s_len = 0;
while (s_len < send_len){
int re_ret = read(pci->file_fd, buff, send_len - s_len);
//printf("buff:[%s]\n", buff);
send_data(pci->sock_fd,buff, MAX_SIZE);
s_len += re_ret;
sleep(1);
if (re_ret == 0){
close(pci->file_fd);
pci->file_fd = -1;
pci->send_status = SEND_FOVER;
break;
}
}
}else if (pci->send_status == SEND_FOVER){
//告诉服务器文件内容发送完毕
send_data(pci->sock_fd, (char*)&pci->send_status, sizeof(pci->send_status));
break;
}
}
close(sockfd);
return 0;
}