Linux 在 Unix 上使用套接字在 C 中发送和接收文件(服务器/客户端)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11229230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending and Receiving a file (Server/Client) in C using socket on Unix
提问by AscaL
First and foremost, thank you all for reading this and helping, I'm very grateful.
Second I'm sorry but i'm still new to this site and English is not my mother language so I could do some formatting and language mistakes. I apologize in advance.
Also, my C knowledge is not that good, but i'm willing to learn and improve.
Now, to the matter at hand:
首先,感谢大家阅读本文并提供帮助,我非常感谢。
其次,我很抱歉,但我还是这个网站的新手,英语不是我的母语,所以我可能会犯一些格式和语言错误。我提前道歉。
另外,我的 C 知识不是很好,但我愿意学习和改进。
现在,关于手头的问题:
What I need to do is to create a Client and a Server, and have the server listen for incoming connections.
Then I have the Client send a quite big text file (I know it will only be ONE file) to the Server.
The Server will then do some operation on the file (it will run a script on the sent file that produces another file in output called "output.txt").
The server then will need to send the output.txt file back to the Client.
我需要做的是创建一个客户端和一个服务器,并让服务器监听传入的连接。
然后我让客户端向服务器发送一个相当大的文本文件(我知道它只会是一个文件)。
然后服务器将对文件进行一些操作(它将在发送的文件上运行一个脚本,在输出中生成另一个名为“output.txt”的文件)。然后服务器需要将 output.txt 文件发送回客户端。
Now, I kinda got how to make a Client and a Server (I read beej guide and some other stuff on this site), even tho I probably made some mistakes. I need some help with the server reciving the file, then calling the script and sending the other file back to the client.
For now what I did is the Server and Client... I don't really know how to go on.
On a side note, I made this files using what I found on this site and on the internet, I hope they are not too messy, as I'm not that good of a programmer.
现在,我有点知道如何制作客户端和服务器(我在这个网站上阅读了 beej 指南和其他一些东西),即使我可能犯了一些错误。我需要一些帮助服务器接收文件,然后调用脚本并将另一个文件发送回客户端。现在我所做的是服务器和客户端......我真的不知道如何继续。
附带说明一下,我使用我在本网站和互联网上找到的内容制作了这些文件,我希望它们不会太乱,因为我不是一个很好的程序员。
This is client.c
这是 client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#define SOCKET_PORT "50000"
#define SOCKET_ADR "localhost"
#define filename "/home/aryan/Desktop/input.txt"
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main()
{
/* Making the client */
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
portno = atoi(SOCKET_PORT);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(SOCKET_ADR);
if (server == NULL)
{
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
/* Time to send the file */
FILE *pf;
unsigned long fsize;
pf = fopen(filename, "rb");
if (pf == NULL)
{
printf("File not found!\n");
return 1;
}
else
{
printf("Found file %s\n", filename);
fseek(pf, 0, SEEK_END);
fsize = ftell(pf);
rewind(pf);
printf("File contains %ld bytes!\n", fsize);
printf("Sending the file now");
}
while (1)
{
// Read data into buffer. We may not have enough to fill up buffer, so we
// store how many bytes were actually read in bytes_read.
int bytes_read = fread(buffer, sizeof(char),sizeof(buffer), pf);
if (bytes_read == 0) // We're done reading from the file
break;
if (bytes_read < 0)
{
error("ERROR reading from file");
}
// You need a loop for the write, because not all of the data may be written
// in one call; write will return how many bytes were written. p keeps
// track of where in the buffer we are, while we decrement bytes_read
// to keep track of how many bytes are left to write.
void *p = buffer;
while (bytes_read > 0)
{
int bytes_written = write(sockfd, buffer, bytes_read);
if (bytes_written <= 0)
{
error("ERROR writing to socket\n");
}
bytes_read -= bytes_written;
p += bytes_written;
}
}
printf("Done Sending the File!\n");
printf("Now Closing Connection.\n");
fclose(pf);
close(sockfd);
return 0;
}
This is server.c:
这是 server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <pthread.h>
#define SOCKET_PORT 50000
#define filename "/home/aryan/Desktop/output.txt"
void error(const char *msg)
{
perror(msg);
exit(1);
}
void* client_thread_proc(void* arg)
{
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
FILE *fp;
int thisfd = (int)arg;
printf("Server %d: accepted = %d\n", getpid(), thisfd);
if (thisfd < 0)
{
printf("Accept error on server\n");
error("ERROR on accept");
return NULL;
}
printf("Connection %d accepted\n", thisfd);
fp = fopen(filename, "a+b");
if (fp == NULL)
{
printf("File not found!\n");
return NULL;
}
else
{
printf("Found file %s\n", filename);
}
/* Time to Receive the File */
while (1)
{
bzero(buffer,256);
n = read(thisfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
n = fwrite(buffer, sizeof(char), sizeof(buffer), fp);
if (n < 0) error("ERROR writing in file");
n = write(thisfd,"I am getting your file...",25);
if (n < 0) error("ERROR writing to socket");
} /* end child while loop */
fclose(fp);
return NULL;
}
void serve_it(int Client)
{
void* arg = (void*)Client;
pthread_t new_thread;
pthread_create( &new_thread, NULL, &client_thread_proc, arg);
}
/* Making Server */
int main()
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
FILE *fp;
signal (SIGCHLD, SIG_IGN);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(SOCKET_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1)
{
printf("Server %d accepting connections\n", getpid());
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
serve_it(newsockfd);
} // serving loop
close(sockfd);
return 0;
}
I'd like some pointers on how to go on...
How do I make a script go on the file i received from client to server?
How do I send the new file back to the same client?
And if you could help me with the errors in the code i'd be grateful.
我想要一些关于如何继续的指示...
如何在从客户端到服务器收到的文件上制作脚本?
如何将新文件发送回同一个客户端?
如果您能帮助我解决代码中的错误,我将不胜感激。
Thank you all and sorry for the long read. Have a nice day!
谢谢大家,很抱歉长时间阅读。祝你今天过得愉快!
采纳答案by Viktor Latypov
First error:
第一个错误:
#define filename = "Home\Desktop\input.txt"
should be
应该
#define filename "Home\Desktop\input.txt"
Otherwise the preprocessor inserts the
否则预处理器插入
= "Home\Desktop\input.txt"
not the
不是
"Home\Desktop\input.txt"
that you expect.
你所期望的。
Second error:
第二个错误:
int bytes_read = read(filename /* THAT IS WRONG, FILE HANDLE MUST BE HERE */, buffer, strlen(buffer) /* also WRONG, must be MAX_BYTES_IN_BUFFER or something */ );
Here you must read from "pf" (you've opened it with the fopen() call) and the last argument must be the number of bytes you want to read. So if you do the strlen(buffer) and the buffer contains some garbage at the beginning of the program's runtime you will get a crash. strlen() must only be called for valid zero-terminated string, it is not the size of the array !
在这里,您必须从“pf”(您已使用 fopen() 调用打开它)中读取,最后一个参数必须是您要读取的字节数。因此,如果您执行 strlen(buffer) 并且在程序运行时开始时缓冲区包含一些垃圾,您将崩溃。strlen() 只能为有效的以零结尾的字符串调用,它不是数组的大小!
EDIT: elaborated server's loop:
编辑:详细说明服务器的循环:
while (1)
{
printf("Server %d accepting connections\n", getpid());
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
serve_it(newsockfd);
} // serving loop
The serve_it():
serve_it():
void serve_int(int Client)
{
void* arg = (void*)Client;
pthread_t new_thread;
pthread_create( new_thread, NULL, &client_thread_proc, arg);
}
void* client_thread(void* arg)
{
int thisfd = (int)arg;
printf("Server %d: accepted = %d\n", getpid(), thisfd);
if (thisfd < 0)
{
printf("Accept error on server\n");
error("ERROR on accept");
return NULL;
}
printf("Connection %d accepted\n", thisfd);
fp = fopen(filename, "a+b");
if (fp == NULL)
{
printf("File not found!\n");
return NULL;
}
else
{
printf("Found file %s\n", filename);
}
/* Time to Receive the File */
while (1)
{
bzero(buffer,256);
n = read(thisfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
n = fwrite(buffer, sizeof(buffer), 1, fp);
if (n < 0) error("ERROR writing in file");
n = write(thisfd,"I am getting your file...",25);
if (n < 0) error("ERROR writing to socket");
} /* end child while loop */
return NULL;
}