简单TFTP协议实现
whitebear
简单实现了传输的功能,基本没有错误和异常处理……
服务器端
<br></br>#include <stdio.h><br></br>#include <stdlib.h><br></br>#include <string.h><br></br>#include <strings.h><br></br>#include <sys><br></br>#include <sys><br></br>#include <netdb.h><br></br>#include <fcntl.h></fcntl.h></netdb.h></sys></sys></strings.h></string.h></stdlib.h></stdio.h>
#define DEBUG 1
#define OPCODE_RRQ (1)
#define OPCODE_WRQ (2)
#define OPCODE_DATA (3)
#define OPCODE_ACK (4)
#define OPCODE_ERR (5)
#define BLOCKSIZE (512)
struct TFTPHeader{
short opcode;
}__attribute__((packed));
struct TFTPWRRQ{
struct TFTPHeader header;
char *filename; // Terminal as \0x00
char *mode; // Terminal as \0x00
}__attribute__((packed));
struct TFTPData{
struct TFTPHeader header;
short block;
void* data;
}__attribute__((packed));
struct TFTPACK{
struct TFTPHeader header;
short block;
}__attribute__((packed));
struct TFTPERR{
struct TFTPHeader header;
short errcode;
char *errmsg; // Terminal as \0x00
}__attribute__((packed));
int sockfd = -1;
struct sockaddr_in remoteaddr;
socklen_t remoteaddrlen = sizeof(remoteaddr);
int main(){
struct servent *serv;
if((serv = getservbyname(“tftp”, “udp”)) == NULL){
fprintf(stderr, “getservbyname(): failed to find domain service info.\n”);
return -1;
}
struct sockaddr_in localaddr;
localaddr.sin_family = PF_INET;
if((localaddr.sin_addr.s_addr = INADDR_ANY) == -1){
perror(“inet_addr()”);
return -1;
}
localaddr.sin_port = serv->s_port;
#if DEBUG
localaddr.sin_port = htons(6969);
#endif
printf(“DBG: tftp port = %d\n”, ntohs(localaddr.sin_port));
struct protoent *proto;
if((proto = getprotobyname(“udp”)) == NULL){
fprintf(stderr, “getprotobyname(): failed to find udp protocol info\n”);
return -1;
}
if((sockfd = socket(PF_INET, SOCK_DGRAM, proto->p_proto)) opcode)){
case OPCODE_RRQ:
tftpread(buffer, bufferlen);
break;
case OPCODE_WRQ:
tftpwrite(buffer, bufferlen);
break;
default:
fprintf(stderr, “Incorrect opcode: %d\n”, ntohs(header->opcode));
break;
}
}
int tftpread(void *buffer, int bufferlen){
printf(“DBG: Dected Opcode = RRQ.\n”);
struct TFTPWRRQ request;
request.filename = (char*)buffer + sizeof(struct TFTPHeader);
printf(“DBG: filename = %s\n”, request.filename);
request.mode = (char*)buffer + sizeof(struct TFTPHeader) +
strlen(request.filename) + 1;
printf(“DBG: mode = %s\n”, request.mode);
if(strcmp(request.mode, “octet”) != 0){
fprintf(stderr, “Only binary mode is supported.\n”);
return 1;
}
//printf(“DBG: remote addr = %s\n”, inet_ntoa(remoteaddr));
printf(“DBG: remote port = %d\n”, ntohs(remoteaddr.sin_port));
struct stat f_stat;
if(stat(request.filename, &f_stat)
客户端
<br></br>#include <stdio.h><br></br>#include <stdlib.h><br></br>#include <string.h><br></br>#include <strings.h><br></br>#include <sys><br></br>#include <sys><br></br>#include <netdb.h><br></br>#include <sys></sys></netdb.h></sys></sys></strings.h></string.h></stdlib.h></stdio.h>
#define DEBUG 1
#define OPCODE_RRQ (1)
#define OPCODE_WRQ (2)
#define OPCODE_DATA (3)
#define OPCODE_ACK (4)
#define OPCODE_ERR (5)
#define BLOCKSIZE (512)
struct TFTPHeader{
short opcode;
}__attribute__((packed));
struct TFTPWRRQ{
struct TFTPHeader header;
char *filename; // Terminal as \0x00
char *mode; // Terminal as \0x00
}__attribute__((packed));
struct TFTPData{
struct TFTPHeader header;
short block;
void* data;
}__attribute__((packed));
struct TFTPACK{
struct TFTPHeader header;
short block;
}__attribute__((packed));
struct TFTPERR{
struct TFTPHeader header;
short errcode;
char *errmsg; // Terminal as \0x00
}__attribute__((packed));
int sockfd = -1;
struct sockaddr_in remoteaddr;
socklen_t remoteaddrlen = sizeof(remoteaddr);
int main(int argc, char **argv){
if(argc != 5){
printf(“Usage: %s host port [get|put] filename\n”, argv[0]);
return 0;
}
char *host = argv[1];
int port = atoi(argv[2]);
int opt = strcmp(argv[3], “get”) == 0 ? 1 : 2;
char *filename = argv[4];
printf(“DBG: host = %s , port = %d , opt = %d , file = %s\n”,
host, port, opt, filename);
struct sockaddr_in remoteaddr;
remoteaddr.sin_family = PF_INET;
if((remoteaddr.sin_addr.s_addr = INADDR_ANY) == -1){
perror(“inet_addr()”);
return -1;
}
remoteaddr.sin_port = htons(port);
struct protoent *proto;
if((proto = getprotobyname(“udp”)) == NULL){
fprintf(stderr, “getprotobyname(): failed to find udp protocol info\n”);
return -1;
}
if((sockfd = socket(PF_INET, SOCK_DGRAM, proto->p_proto)) opcode) == OPCODE_ERR){
struct TFTPERR *err = (struct TFTPERR*)buffer;
printf(“Error packet dected with code %d\n”, ntohs(err->errcode));
return 1;
}
if(ntohs(header->opcode) == OPCODE_DATA){
struct TFTPData *data = (struct TFTPData*)buffer;
printf(“Receiving block %d\n”, ntohs(data->block));
fwrite(&data->data, recvlen - 4, 1, fp);
struct TFTPACK ack;
ack.header.opcode = htons(OPCODE_ACK);
ack.block = data->block;
if(sendto(sockfd, &ack, sizeof(ack), 0,
(struct sockaddr*)&remoteaddr, sizeof(remoteaddr))