C 套接字发送客户端服务器文件
我编写了一个应用程序,其中客户端使用使用tcp协议的套接字向服务器发送文件 我的服务器是多线程的(带有Pthread) 只有一个问题,将文件复制到服务器比原始文件小(大约2公里)。为什么? 这是我的客户机代码,它开始键入./client filename filenamecopyC 套接字发送客户端服务器文件,c,sockets,pthreads,C,Sockets,Pthreads,我编写了一个应用程序,其中客户端使用使用tcp协议的套接字向服务器发送文件 我的服务器是多线程的(带有Pthread) 只有一个问题,将文件复制到服务器比原始文件小(大约2公里)。为什么? 这是我的客户机代码,它开始键入./client filename filenamecopy #include <netdb.h> #include <netinet/in.h> #include <string.h> #include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
int fileSEND(char *server, int PORT, char *lfile, char *rfile){
int socketDESC;
struct sockaddr_in serverADDRESS;
struct hostent *hostINFO;
FILE * file_to_send;
int ch;
char toSEND[1];
char remoteFILE[4096];
int count1=1,count2=1, percent;
hostINFO = gethostbyname(server);
if (hostINFO == NULL) {
printf("L'adresse ip du serveur n'est pas accesible\n");
return 1;
}
socketDESC = socket(AF_INET, SOCK_STREAM, 0);
if (socketDESC < 0) {
printf("Erreur création socket\n");
return 1;
}
serverADDRESS.sin_family = hostINFO->h_addrtype;
memcpy((char *) &serverADDRESS.sin_addr.s_addr, hostINFO->h_addr_list[0], hostINFO->h_length);
serverADDRESS.sin_port = htons(PORT);
if (connect(socketDESC, (struct sockaddr *) &serverADDRESS, sizeof(serverADDRESS)) < 0) {
printf("Erreur de connection\n");
return 1;
}
file_to_send = fopen (lfile,"r");
if(!file_to_send) {
printf("Erreur de lecture du fichier\n");
close(socketDESC);
return 0;
} else {
long fileSIZE;
fseek (file_to_send, 0, SEEK_END); fileSIZE =ftell (file_to_send);
rewind(file_to_send);
sprintf(remoteFILE,"FBEGIN:%s:%i\r\n", rfile, fileSIZE);
send(socketDESC, remoteFILE, sizeof(remoteFILE), 0);
percent = fileSIZE / 100;
while((ch=getc(file_to_send))!=EOF){
toSEND[0] = ch;
send(socketDESC, toSEND, 1, 0);
if( count1 == count2 ) {
printf("33[0;0H");
printf( "\33[2J");
printf("Nom du fichier: %s\n", lfile);
printf("Taille du fichier: %i Kb\n", fileSIZE / 1024);
printf("Poucentage : %d%% ( %d Kb)\n",count1 / percent ,count1 / 1024);
count1+=percent;
}
count2++;
}
}
fclose(file_to_send);
close(socketDESC);
return 0;
}
int main(int argc, char* argv[])
{
fileSEND("127.0.0.1", 31338, argv[1], argv[2]);
return 0;
}
#包括
#包括
#包括
#包括
int fileSEND(char*服务器、int端口、char*lfile、char*rfile){
int socketDESC;
serverADDRESS中的结构sockaddr_;
结构主机*主机信息;
文件*要发送的文件;
int-ch;
char-toSEND[1];
字符远程文件[4096];
int count1=1,count2=1,百分比;
hostINFO=gethostbyname(服务器);
if(hostINFO==NULL){
printf(“可接受的服务地址”);
返回1;
}
socketDESC=socket(AF_INET,SOCK_STREAM,0);
如果(socketDESC<0){
printf(“Erreur création socket\n”);
返回1;
}
serverADDRESS.sin_family=hostINFO->h_addrtype;
memcpy((char*)&serverADDRESS.sin\u addr.s\u addr,hostINFO->h\u addr\u list[0],hostINFO->h\u length);
serverADDRESS.sin_port=htons(端口);
if(connect(socketDESC,(struct sockaddr*)&serverADDRESS,sizeof(serverADDRESS))<0){
printf(“连接错误”);
返回1;
}
文件发送=fopen(lfile,“r”);
如果(!要发送的文件){
printf(“费希尔讲座的错误”);
关闭(socketDESC);
返回0;
}其他{
长文件大小;
fseek(文件发送,0,搜索结束);fileSIZE=ftell(文件发送);
倒带(文件发送);
sprintf(远程文件,“FBEGIN:%s:%i\r\n”,rfile,fileSIZE);
发送(socketDESC,remoteFILE,sizeof(remoteFILE),0);
百分比=文件大小/100;
while((ch=getc(文件发送))!=EOF){
toSEND[0]=ch;
发送(socketDESC,toSEND,1,0);
如果(count1==count2){
printf(“33[0;0H”);
printf(“\33[2J”);
printf(“文件名:%s\n”,lfile);
printf(“Taille du fichier:%i Kb\n”,文件大小/1024);
printf(“百分比:%d%%(%d Kb)\n”,计数1/百分比,计数1/1024);
count1+=百分比;
}
count2++;
}
}
fclose(文件发送到文件发送);
关闭(socketDESC);
返回0;
}
int main(int argc,char*argv[])
{
fileSEND(“127.0.0.1”,31338,argv[1],argv[2]);
返回0;
}
以及服务器,它仅通过./server启动
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#define PORT 31338
int parseARGS(char **args, char *line){
int tmp=0;
args[tmp] = strtok( line, ":" );
while ( (args[++tmp] = strtok(NULL, ":" ) ) != NULL );
return tmp - 1;
}
int client(void *ptr){
int connectSOCKET;
connectSOCKET = (int ) ptr;
char recvBUFF[4096];
char *filename, *filesize;
FILE * recvFILE;
int received = 0;
char tempstr[4096];
char *header[4096];
/*int i=0;
while(i<993199) {
i++;*/
while(1){
if( recv(connectSOCKET, recvBUFF, sizeof(recvBUFF), 0) ){
if(!strncmp(recvBUFF,"FBEGIN",6)) {
recvBUFF[strlen(recvBUFF) - 2] = 0;
parseARGS(header, recvBUFF);
filename = header[1];
filesize = header[2];
printf("Fichier: %s\n", filename);
printf("Taille: %d Kb\n", atoi(filesize) / 1024);
}
recvBUFF[0] = 0;
recvFILE = fopen ( filename,"w" );
while(1){
if( recv(connectSOCKET, recvBUFF, 1, 0) != 0 ) {
fwrite (recvBUFF , sizeof(recvBUFF[0]) , 1 , recvFILE );
received++;
recvBUFF[0] = 0;
} else {
printf("Progression: %s [ %d of %s bytes]\n", filename, received , filesize);
return 0;
}
}
return 0;
} else {
printf("Client déconnecté\n");
}
return 0;
}
}
int main()
{
int socketINDEX = 0;
int listenSOCKET, connectSOCKET[4096];
socklen_t clientADDRESSLENGTH[4096];
struct sockaddr_in clientADDRESS[4096], serverADDRESS;
pthread_t threads[4096];
listenSOCKET = socket(AF_INET, SOCK_STREAM, 0);
if (listenSOCKET < 0) {
printf("Peut pas crée socket\n");
close(listenSOCKET);
return 1;
}
serverADDRESS.sin_family = AF_INET;
serverADDRESS.sin_addr.s_addr = htonl(INADDR_ANY);
serverADDRESS.sin_port = htons(PORT);
if (bind(listenSOCKET, (struct sockaddr *) &serverADDRESS, sizeof(serverADDRESS)) < 0) {
printf("Peut pas trouver la socket\n");
close(listenSOCKET);
return 1;
}
listen(listenSOCKET, 5);
clientADDRESSLENGTH[socketINDEX] = sizeof(clientADDRESS[socketINDEX]);
int i=0;
/*while(i<993199) {
i++;*/
while(1){
connectSOCKET[socketINDEX] = accept(listenSOCKET, (struct sockaddr *) &clientADDRESS[socketINDEX], &clientADDRESSLENGTH[socketINDEX]);
if (connectSOCKET[socketINDEX] < 0) {
printf("Connection refusé\n");
close(listenSOCKET);
return 1;
}
pthread_create( &threads[socketINDEX], NULL, client, connectSOCKET[socketINDEX]);
if(socketINDEX=4096) {
socketINDEX = 0;
} else {
socketINDEX++;
}
}
close(listenSOCKET);
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义端口31338
int parseARGS(字符**参数,字符*行){
int-tmp=0;
args[tmp]=strtok(行“:”);
while((args[++tmp]=strtok(NULL,“:”)!=NULL);
返回tmp-1;
}
内部客户端(void*ptr){
int连接插座;
connectSOCKET=(int)ptr;
char recvBUFF[4096];
字符*文件名,*文件大小;
文件*recvFILE;
接收到的int=0;
char-tempstr[4096];
字符*头[4096];
/*int i=0;
而(i2个问题:
您的客户端发送一个带有FBEGIN:filename:size标头的4K块。服务器尝试在一个4K块中读取该块。recv()
可能返回的缓冲区少于一个完整的缓冲区(只有1个字节)
服务器读取文件后未关闭该文件。这可能导致文件大小不一致(关闭文件时缓冲数据将被刷新)
这本身不是一个bug,而是一个性能问题:一次读取/写入/发送/接收一个字节是S-L-O-W。您应该在更大的块中完成所有操作(即使只有1K也会大大提高性能)。请记住“recv()
可能会部分完成”上面提到的问题。您能再解释一下这个问题吗?好的,谢谢您的回答。1)我必须将4096改为1024?2)我没有倒立,我想添加的是fclose(recvFILE);关闭后(listenSOCKET)?