我需要将文件从一个应用程序传输到同一台机器上的另一个应用程序。我编写了传输数据包结构的代码,该数据包结构具有以下字段:
- 序号
- 圆形的
- data,这是一个
unsigned char
指示要传输的数据 - length
read
,表示使用函数读取了多少字节 - crc,这是目前的默认字符串
和一个参数last,表示它是最后一个数据包,因此可以关闭文件和连接。
此代码非常适用于 ASCII 文件,但是,当我使用它传输二进制文件时,两个文件的差异不匹配。我无法弄清楚问题所在。有人能帮我吗?
这是我的发件人的代码。它连接到端口 4950 上的接收器。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define DATA 170
#define SERVERPORT "4950" // the port users will be connecting to
typedef struct packet_ {
unsigned short int seq;
unsigned short int round;
unsigned short int last;
unsigned short int length;
unsigned char data[DATA];
unsigned char crc[17];
} packet;
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
int max_seq_no = 10;
packet send;
FILE *fp;
unsigned short int seq =0, round =0;
long int totalBytes = 0;
unsigned short int bytes_read =0;
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
fp = fopen("wilde-tiobe.txt", "rb");
printf("Size of packet : %d", sizeof send);
while (1) {
memset((void *) &send, '\0', sizeof send);
send.seq = seq;
send.round = round;
memset(send.data, '\0', DATA);
bytes_read = read(fileno(fp), send.data, DATA );
send.length = bytes_read;
if (bytes_read < DATA) {
send.last = 1;
printf("****last byte***\n");
}
strcpy(send.crc, "yet to calcula\0");
totalBytes+= bytes_read;
//if(bytes_read == 0) break;
if ((numbytes = sendto(sockfd, &send, sizeof send, 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
usleep(60000);
if (send.last) break;
}
fclose(fp);
printf("Total bytes transferred : %lu\n", totalBytes);
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
这是我的接收器的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MYPORT "4950" // the port users will be connecting to
#define MAXBUFLEN 196
#define DATA 170
typedef struct packet_ {
unsigned short int seq;
unsigned short int round;
unsigned short int last;
unsigned short int length;
unsigned char data[DATA];
unsigned char crc[17];
} packet;
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
FILE *fp;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
packet * recv, recv_packet;
fp = fopen("wtf.bmp", "wb");
printf("size of packet :%d", sizeof(packet));
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
freeaddrinfo(servinfo);
addr_len = sizeof their_addr;
while(1) {
printf("listener: waiting to recvfrom...\n");
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN , 0,
(struct sockaddr *)&their_addr,
&addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
printf("listener: got packet from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s));
printf("listener: packet is %d bytes long\n", numbytes);
//printf("listener: packet contains \"%s\"\n", buf);
recv = (packet *) buf;
if (!recv_packet.data) {
printf("NO memory\n");
break;
}
memset(&recv_packet, 0, sizeof recv_packet);
recv_packet.seq = recv->seq;
recv_packet.round = recv->round;
recv_packet.last = recv->last;
recv_packet.length = recv->length;
memset(recv_packet.data, '\0', DATA);
strncpy(recv_packet.data, recv->data, recv_packet.length);
strncpy(recv_packet.crc, recv->crc, 17);
//printf(" len: %hu and data: %s \n", recv_packet.length, recv_packet.data);
write(fileno(fp), recv_packet.data, recv_packet.length);
if (recv_packet.last) {
printf("Last packet\n");
break;
}
}
fclose(fp);
close(sockfd);
return 0;
}