这不是全部代码。
这是正常工作的文件,如文本文件,但不工作的tar.gz和二进制文件传输请帮助我。
以及如何使用套接字发送内存块。
server.c
void main()
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char buf[16384];
char remotefile[MAXDATASIZE];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(my_addr.sin_zero, ' ', sizeof my_addr.sin_zero);
printf("call bindingn");
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1)
{
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction");
exit(1);
}
while(1)
{ // main accept() loop
sin_size = sizeof their_addr;
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
perror("accept");
exit(1);
continue;
}
printf("server: got connection from %sn",inet_ntoa(their_addr.sin_addr));
if (!fork())
{ // this is the child process
if ((byt=recv(new_fd, remotefile, MAXDATASIZE-1, 0)) == -1)
{
perror("server recv");
exit(1);
}
int serverfile_fd;
size_t result;
printf("nremotefile in val1 is %sn",remotefile);
if((serverfile_fd = open(remotefile,O_RDONLY)) < 0)
{
printf("error at remotefilen");
exit(1);
}
else
{
read(serverfile_fd, &buf[0], sizeof(buf));
}
//printf("file isn%s", buf);
/* 3. sending buf in val 0*/
if (send(new_fd, buf, 16384, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
client.c
int remote_to_local(const char *remotehost,const char *remotefile,const char *localfile)
{
int sockfd, numbytes,i = 0,j = 0;
char buf[16384];
struct hostent *he;
struct sockaddr_in s_addr; // connector's address information
printf("n");
printf("Remotehost is %sn", remotehost);
if ((he=gethostbyname(remotehost)) == NULL)
{ // get the host info
perror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
s_addr.sin_family = AF_INET; // host byte order
s_addr.sin_port = htons(PORT); // short, network byte order
s_addr.sin_addr = *((struct in_addr *)he->h_addr);
//inet_aton(he->h_addr, &s_addr.sin_addr);
memset(s_addr.sin_zero, ' ', sizeof s_addr.sin_zero);
if (connect(sockfd, (struct sockaddr *)&s_addr, sizeof s_addr) == -1)
{
perror("connect");
exit(1);
}
//send(sockfd, remotefile, MAXDATASIZE-1, 0);
val[0] = 1;
printf("Val 0 is %dn", val[0]);
printf("Val 1 is %dn", val[1]);
/*1 sending val in r to l*/
if (send(sockfd, val, MAXDATASIZE-1, 0) == -1)
perror("send");
printf("remotefile is %sn",remotefile);
/* 2 sending remotefile in r to l*/
if (send(sockfd, remotefile, MAXDATASIZE-1, 0) == -1)
perror("send");
/* 3. recieve buf in r to l */
if ((numbytes=recv(sockfd, buf, 16384, 0)) == -1)
{
perror("recv");
exit(1);
}
buf[numbytes] = ' ';
//printf("Received: n%s",buf);
int clientfile_fd;
printf("Local file is %sn",localfile);
if((clientfile_fd = open(localfile,O_CREAT|O_WRONLY,0777)) < 0)
{
printf("error at remotefilen");
exit(1);
}
else
{
//read(clientfile_fd, &buf[0], sizeof(buf));
int result = strlen(buf);
//printf("Result size is %dn",result);
open(localfile,O_TRUNC);
write(clientfile_fd, &buf[0], result);
}
close(sockfd);
return 0;
}
检查你所有的代码并修复/更改所有你:
- 不能正确处理系统调用返回的结果recv()。如果返回正值,则该值为唯一安全值查看有多少数据被读入缓冲区的方法。
- 删除所有strlen(), printf("%s…")等无用,(二进制数据可能包含null,因此操作将提前完成)或危险(二进制数据根本不包含null)因此呼叫是UB)。
遵循接收文件的逻辑已经比您所拥有的要好得多。但是你的代码还有很多问题:
FILE *received_file;
received_file = fopen(FILENAME, "w");
...
//copy logic, copies data received from the socket into the file as is.
while (((len = recv(client_socket, buffer, BUFSIZ, 0)) > 0))
{
fwrite(buffer, sizeof(char), len, received_file);
}
fclose(received_file);
close(client_socket);
接收被连续调用,直到你收到0或一个负数,如果你收到0,这意味着你需要关闭套接字,因为传输已经完成,对等端也关闭了它的连接。文件句柄应该在accept之后创建。
底线是你的代码需要一个全面的修订,因为它太长了,它应该做什么,它是基于完全错误的假设。在尝试这样做之前,先阅读网络编程。套接字编程是一个高级的主题,没有正确的理解你将失败。