我正在尝试制作文件传输程序。我目前正在对C服务器进行编程,并使用简短的Python脚本作为客户端。当我尝试将文件名从Python发送到C时,recv函数(在C中)返回未定义的错误。它一次收到文件名的一半。这是代码:C服务器(指出recv功能有问题):
#define BUFFER 2000000
#define HEADERSIZE 20
#define PORT 9342
#define FGET "FGET"
#define UPLD "UPLD"
typedef struct timeval timeval_t;
int i;
fd_set readlist, sockets;
void* sendf(void* sock){
printf("File Descriptor: %d\n", *(int*)sock);
fflush(stdout);
char* filename = (char*) malloc(21*sizeof(char));
ssize_t result = recv(*(int*)sock, filename, 20+1, 0);
if (result != 0){
printf("%s", strerror(errno));
exit(0);
}
printf("Filename: ");
puts(filename);
FILE* sfile = fopen(filename, "rb");
free(filename);
fseek(sfile, 0, SEEK_END);
unsigned long long filesize = ftell(sfile);
fseek(sfile, 0, SEEK_SET);
char* content = malloc(BUFFER);
for(i=0; i<=ceil(filesize/BUFFER); ++i){
if (filesize >= BUFFER){
fread(content, BUFFER, 1, sfile);
filesize-=BUFFER;
fseek(sfile, filesize-1, SEEK_END);
} else{
fread(content, filesize, 1, sfile);
}
content = realloc(content, BUFFER);
}
fclose(sfile);
char* header = malloc(HEADERSIZE);
sprintf(header, "%20llu", filesize);
send(*(int*)sock, header, 20, 0);
send(*(int*)sock, content, filesize, 0);
free(filename);
free(content);
free(header);
return NULL;
}
void* receivef(void* sock){
printf("Function not written yet");
return NULL;
}
int main(){
chdir("/Users/reimeytal/Desktop/Fileserver");
int sock = socket(AF_INET, SOCK_STREAM, 0);
pthread_t thread;
timeval_t timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
struct sockaddr_in server;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
FD_ZERO(&sockets);
FD_SET(sock, &sockets);
bind(sock, (struct sockaddr*)&server, sizeof(server));
listen(sock, 5);
int maxsock = sock;
int clientsock;
char* msghdr = (char*) malloc(5*sizeof(char));
while (1){
readlist = sockets;
select(FD_SETSIZE, &readlist, NULL, NULL, &timeout);
for(i=0; i<=maxsock; i++){
if(FD_ISSET(i, &readlist)){
if(i==sock){
clientsock = accept(sock, NULL, NULL);
FD_SET(clientsock, &sockets);
if(clientsock>sock){
maxsock = clientsock;
}
} else{
printf("Incoming message from %d\n", i);
fflush(stdout);
recv(i, msghdr, 5, 0);
clientsock = i;
if(strcmp(msghdr, FGET) == 0){
pthread_create(&thread, NULL, sendf, (int *)&clientsock);
}/*else if(strcmp(msghdr, UPLD) == 0){
pthread_create(&thread, NULL, receivef, (int*)&i);
}else{
puts("ERROR: Received invalid message header");
}*/
msghdr = (char *) realloc(msghdr, 5*sizeof(char));
}
}
}
}
return 0;
运行时的结果:
Incoming message from 4
File Descriptor: 4
Incoming message from 4
Incoming message from 4
Undefined error: 0
Python客户端:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 9342))
sock.send(b'FGET\0')
sock.send(b'abcdeftghijklmno.txt\0')
[如果有人需要我澄清/添加一些内容,我很乐意这样做。谢谢
有一些错误,第一个:
ssize_t result = recv(*(int*)sock, filename, 20+1, 0);
if (result != 0){
printf("%s", strerror(errno));
exit(0);
}
recv
返回写入的字节数,因此应检查if (result <= 0)
。
在您的情况下,recv
返回0,从技术上讲这不是错误代码,它仅表示另一端的套接字关闭了连接。 (这就是为什么您会得到未定义的错误的原因。)
那么为什么另一个插座关闭?好吧,因为您的Python脚本可能已在服务器读取您的消息时结束。在最后一次sock.send
调用之后,Python程序完成,清除其所有资源(包括套接字)并终止。然后关闭套接字。
这是一个时间问题:如果您很幸运,Python程序尚未清理其资源,服务器有足够的时间读取答复。这也解释了为什么它适用于@wierzmar。
[要修复它,请等待确认消息(可以从服务器发送),然后在Python端接收。或者只是在Python脚本的末尾添加sleep(10)
-不太好,但是如果您只是测试一些东西,它就可以使用。