如何使用TCP/IP协议从Android接收文本文件到C。我的数据丢失了
我已经编写了一个从Android到C的文件接收代码,但问题是我接收到的数据丢失。当接收到的文本文件与原始文本文件进行检查时,字节不匹配。如何根除这一现象?我已经给出了代码以供参考`如何使用TCP/IP协议从Android接收文本文件到C。我的数据丢失了,c,sockets,system-calls,tcp-ip,C,Sockets,System Calls,Tcp Ip,我已经编写了一个从Android到C的文件接收代码,但问题是我接收到的数据丢失。当接收到的文本文件与原始文本文件进行检查时,字节不匹配。如何根除这一现象?我已经给出了代码以供参考` #include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<sys/ioctl.h> #include<sys/
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/socket.h>
int receive_text(long int new_socket)
{
int buffersize = 0, recv_size = 0, size = 0, read_size, write_size;
char verify = '1';
int errno;
FILE *text;
char *pBuf;
//Find the size of the text
recv(new_socket, (char *)&size, sizeof(int), 0);
//Send our verification signal
//send(new_socket, &verify, sizeof(char), 0);
text = fopen("/home/sosdt009/Desktop/received.txt", "w");
if (text == NULL)
{
puts("Error has occurred. Text file could not be opened \n");
return -1;
}
//Loop while we have not received the entire file yet
while (recv_size < size)
{
ioctl(new_socket, FIONREAD, &buffersize);
//We check to see if there is data to be read from the socket
if (buffersize > 0)
{
pBuf = malloc(buffersize);
if (!pBuf)
{
fprintf(stderr, "Memory Error. Cannot allocate!\n");
exit(-1);
}
//memset(pBuf,0,buffersize);
read_size = recv(new_socket, pBuf, buffersize, 0);
if (read_size < 0)
{
printf("%s", strerror(errno));
}
//Write the currently read data into our text file
write_size = fwrite(pBuf, 1, buffersize, text);
free(pBuf);
printf("%d \n", write_size);
//Increment the total number of bytes read
recv_size += write_size;
printf(" %d \n", recv_size);
}
}
fclose(text);
return 1;
}
int main(int argc , char *argv[]) {
int socket_desc , new_socket, c, read_size, buffer = 0;
struct sockaddr_in server , client;
char *readin;
//Create socket
socket_desc = socket(AF_INET,SOCK_STREAM,0);
if (socket_desc == -1)
{
printf("Could not create socket:");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 6777 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("Bind completed");
//Listen
listen(socket_desc,3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
if((new_socket = accept(socket_desc,(struct sockaddr *)&client,(socklen_t *)&c)) )
{
puts("Connection accepted");
}
fflush(stdout);
close(socket_desc);
if (new_socket<0)
{
perror("Accept Failed");
return 1;
}
while(1)
{
receive_text(new_socket);
}
close(socket_desc);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int接收_文本(长int新_套接字)
{
int buffersize=0,recv_size=0,size=0,read_size,write_size;
char verify='1';
int errno;
文件*文本;
char*pBuf;
//查找文本的大小
recv(新的_插座,字符*)和大小,sizeof(int),0;
//发送我们的验证信号
//发送(新的_套接字,&verify,sizeof(char),0);
text=fopen(“/home/sosdt009/Desktop/received.txt”,“w”);
if(text==NULL)
{
puts(“发生错误。无法打开文本文件\n”);
返回-1;
}
//循环,而我们还没有收到整个文件
while(recv_size0)
{
pBuf=malloc(缓冲区大小);
if(!pBuf)
{
fprintf(stderr,“内存错误。无法分配!\n”);
出口(-1);
}
//memset(pBuf,0,buffersize);
read_size=recv(新的_套接字,pBuf,buffersize,0);
如果(读取大小<0)
{
printf(“%s”,strerror(errno));
}
//将当前读取的数据写入文本文件
write_size=fwrite(pBuf,1,buffersize,text);
免费(pBuf);
printf(“%d\n”,写入大小);
//增加读取的总字节数
记录大小+=写入大小;
printf(“%d\n”,记录大小);
}
}
fclose(文本);
返回1;
}
int main(int argc,char*argv[]){
intsocket\u desc,new\u socket,c,read\u size,buffer=0;
服务器、客户端中的结构sockaddr_;
char*readin;
//创建套接字
socket\u desc=socket(AF\u INET,SOCK\u STREAM,0);
如果(套接字描述==-1)
{
printf(“无法创建套接字:”);
}
//在结构中准备sockaddr_
server.sinu family=AF\u INET;
server.sin\u addr.s\u addr=INADDR\u ANY;
server.sin_port=htons(6777);
//束缚
if(绑定(socket_desc,(struct sockaddr*)&server,sizeof(server))<0
{
看跌期权(“绑定失败”);
返回1;
}
看跌期权(“绑定完成”);
//听
听(插座描述,3);
//接受和传入连接
puts(“等待传入连接…”);
c=sizeof(结构sockaddr_in);
if((new_socket=accept(socket_desc,(struct sockaddr*)和client,(socklen_t*)和c)))
{
看跌期权(“已接受连接”);
}
fflush(stdout);
关闭(插座描述);
如果(新插座在这里
recv()
告诉您它在当前迭代中收到了多少字节,但不包括read\u size
字节
这里呢
write_size = fwrite(pBuf, 1, buffersize, text);
您忽略接收的字节数,但总是写入buffersize
通过将实际接收的数据量写入目标文件来解决此问题:
write_size = fwrite(pBuf, 1, read_size, text);
调用recv()
接收到的字节数将完全忽略任何错误检查
在传输二进制数据时,您还需要确保不会绊倒
发送方和接收方上整数值的宽度可能不同
发送方和接收方的端点不同
要解决上述第一个可能的问题,请使用定义良好的位宽度数据类型。此处int32\u t
而不是int
或可能是未签名的学究:unint32\u t
对于第二个可能的陷阱,以网络字节顺序传输数据。为了实现这一点,不要发送普通的int
(或uint32\u t
),而是通过调用htonl()
,将其转换为网络字节顺序(在发送之前)。在接收端,然后使用ntohl()
将其转换回主机字节顺序
发送方在传输过程中关闭套接字的情况将被忽略,但应通过测试recv()
的结果与0
进行比较来处理,这表明发送方关闭了套接字
在调用accept()
时将int c
强制转换为socklen\t
,也可能会引发未定义的行为
来解决这个问题,而不是
int c;
定义
socklen_t c;
另外,代码关闭socket\u desc
两次,并且根本不关闭new\u socket
Also3正在做什么
测试数据是否可用是有意义的,因为套接字的缓冲区是由内核异步填充到程序的,所以调用ioctl()
返回的值可能在一瞬间就过时了
只需删除对ioctl()
的调用,并定义一个固定大小的缓冲区来读取。recv()
将阻止,直到数据可用。我已根据上面的注释修改了代码,但仍然丢失了数据。您可能希望在收到时记录size
的值,并验证其正确性。
socklen_t c;
ioctl(new_socket, FIONREAD, &buffersize);