关于作者

局域网文件传输小程序

上一篇 / 下一篇  2010-05-13 21:22:25 / 个人分类:linux

1引言

在学了计算机网络之后,为了更好地理解、掌握和应用一些网络知识,需要用做一个课程设计等方式来巩固网络知识和应用这些知识。TCP协议是在实际应用中应用广泛的协议,因而掌握TCP协议具有十分重要的意义。

2总体设计

2.1系统或算法框架设计

本系统有两部分:一个服务器端,负责接收文件;一个客户端,负责发送文件。

系统采用套接字(socket)通信,套接字(socket)是一种通信机制,客户/服务器系统的开发工作既可以在本地单机上进行,也可以跨网络进行。

2.2功能设计

程序的功能是局域网传输文件。

2.3平台设计

硬件:不限

操作系统:GNU/Linux系统

2.4数据结构的设计

 struct sockaddr_in{
   short sin_family;/socket()系统调用的协议族如AF_INET/
   u_short sin_port;/*网络字节次序形式的端口号码*/
   struct in_addr sin_addr;/*网络字节次序形式的网络地址*/
   char sin_zero[8];
  }

2.5接口设计

ssize_t readline(int fd, void * vptr, size_t maxlen)

;

接收一个包含文件名的TCP

int socket(int family,int type,int protocol)
  其中:

(1)family指明套节字族,其值包括:
  AF_UNIX  (UNIX内部协议族)
  AF_INET  (Iternet协议)
  AF_NS (XeroxNs协议,TCP/IP编程取该值)
  AF_IMPLINK (IMP链接层)

在本系统中,用AF_INET
  (2)type指明套接字类型,取值有:
  SOCK_STREAM    (流套接字)
  SOCK_DGRAM    (数据报套接字)
  SOCK_RAW      (原始套接字)
  SOCK_SEQPACKET  (定序分组套接字)

在本系统中,用SOCK_STREAM

详见Linux的帮助手册:man socket

3详细设计

3.1原理

运行服务器server,服务器监听9734端口,等待客户端的请求;客户端发出连接请求,服务器接受请求,建立连接。客户端发送一个TCP包,里面包含需要传输的文件名,服务器端接收到含有文件名的TCP包后在本地磁盘创建文件。然后客户端开始发送文件,每次发送2048个字节(最后一次可能小于2048字节),直到文件传输完成。

3.2服务器端关键代码

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

server_address.sin_family = AF_INET;

server_address.sin_addr.s_addr = htonl(INADDR_ANY);

server_address.sin_port = htons(PORT);

bind(server_sockfd, (struct sockaddr *) &server_address,

sizeof(server_address));

listen(server_sockfd, 5);

说明:打开socket,进行监听所有连接请求


while(len = read(client_sockfd, buffer, LENGTH))

{

     if(len < 0)

     {

          printf("socket read error\n");

          exit(1);

     }

     if(fwrite(buffer, 1, len, fp) < 0)

    {

         printf("Error while writing to file %s",filename);

         exit(1);

    }

}

说明:一边从客户端接收文件,一边把文件保存到本地磁盘。


if(readline(client_sockfd, buffer, LENGTH) < 0)

{

printf("Error! Can not receive packege.\n");

exit(1);

}

说明:接收一个包含文件名的TCP


3.3客户端关键代码

sockfd = socket(AF_INET, SOCK_STREAM, 0);

address.sin_family = AF_INET;

address.sin_addr.s_addr = inet_addr(argv[2]);

address.sin_port = htons(9734);

len = sizeof(address);

result = connect(sockfd, (struct sockaddr *)&address, len);

说明:打开socket,向服务器端发出连接请求


while(len = fread(buffer, 1, LENGTH, fp))

{

if(len < 0)

{

printf("read file error\n");

exit(1);

}

if(write(sockfd, buffer, len) < 0)

{

printf("Error while write to the socket.\n");

exit(1);

}

}

说明:一边从本地读文件,一边向服务器端发送文件


write(sockfd, filename, strlen(filename));

printf("will transferfile:%s\n",filename);

说明:向服务器端发送文件名。


3.3客户端详细设计

#define LENGTH 2048

int main(int argc, char *argv[])

{

int sockfd;

int len;

struct sockaddr_in address;

int result;

char *buffer[LENGTH+1];

char filename[LENGTH+1];

FILE *fp;

int i;


if(argc != 3)

{

printf("Error! Parameter is not right,please see ./client2 -h\n");

exit(1);

}

else if((*argv[1] == '-') && (*(argv[1]+1) == 'h'))

{

printf("Usage: ./client <filename> <serverIP>\n");

exit(1);

}

else

{

memcpy(filename, argv[1], strlen(argv[1]));

filename[strlen(argv[1])] = '\n';

filename[strlen(argv[1]) + 1] = 0;

}

//打开文件

if((fp = fopen(argv[1],"rb+")) == NULL)

{

printf("Error! Can not open file %s", filename);

exit(1);

}


sockfd = socket(AF_INET, SOCK_STREAM, 0);

address.sin_family = AF_INET;

address.sin_addr.s_addr = inet_addr(argv[2]);

address.sin_port = htons(9734);

len = sizeof(address);

result = connect(sockfd, (struct sockaddr *)&address, len);


if(result == -1)

{

perror("oops:client1");

exit(1);

}


write(sockfd, filename, strlen(filename));

printf("will transfer file:%s\n",filename);


while(len = fread(buffer, 1, LENGTH, fp))

{

if(len < 0)

{

printf("read file error\n");

exit(1);

}

if(write(sockfd, buffer, len) < 0)

{

printf("Error while write to the socket.\n");

exit(1);

}

}

fclose(fp);

close(sockfd);

printf("file %s transferred !\n",argv[1]);


return 0;

}


3.2服务器端详细设计

#define PORT 9734

#define LENGTH 2048


int main(int argc, char *argv[])

{

int server_sockfd, client_sockfd;

int server_len, client_len;

struct sockaddr_in server_address;

struct sockaddr_in client_address;

int i,len;

FILE *fp;

char filename[LENGTH+1];

ssize_t readlilne(int fd, void *vptr, size_t maxlen);


//缓存

char buffer[LENGTH+1];


server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

server_address.sin_family = AF_INET;

server_address.sin_addr.s_addr = htonl(INADDR_ANY);

server_address.sin_port = htons(PORT);

bind(server_sockfd, (struct sockaddr *) &server_address,

sizeof(server_address));

listen(server_sockfd, 5);



while(1)

{

printf("server waiting...\n");

client_len = sizeof(client_address);

client_sockfd = accept(server_sockfd,

(struct sockaddr *) &client_address, &client_len);


printf("reading filename......\n");


//接收一个包含文件名的TCP

if(readline(client_sockfd, buffer, LENGTH) < 0)

{

printf("Error! Can not receive packege.\n");

exit(1);

}

buffer[strlen(buffer) - 1] = 0;

memcpy(filename, buffer, LENGTH + 1);

printf("will save to file:%s\n",buffer);


//打开文件

if((fp = fopen(filename, "wb+") ) == NULL)

{

printf("Error! Can not open file:%s", filename);

exit(1);

}


//接收文件

while(len = read(client_sockfd, buffer, LENGTH))

{


if(len < 0)

{

printf("socket read error\n");

exit(1);

}

if(fwrite(buffer, 1, len, fp) < 0)

{

printf("Error while writing to file %s",filename);

exit(1);

}

}


fclose(fp);

close(client_sockfd);

printf("file %s received!\n");

}


close(server_sockfd);


return 0;

}


ssize_t readline(int fd, void * vptr, size_t maxlen)

{

ssize_t n, rc;

char c, *ptr;


ptr = vptr;

for (n = 1; n < maxlen; n++) {

again:

if ((rc = read(fd, &c, 1)) == 1) {

*ptr++ = c;

if (c == '\n') {

break;

}

} else if (rc == 0) { /* EOF */

*ptr = 0;

return (n - 1);

} else {

if (errno == EINTR) {

goto again;

}

return (-1);

}

}


*ptr = 0;

return (n);

}

【参考文献】

Linux程序设计(3)Neil Matthew , Richard Stones著,陈健、宋健健译,人民邮电出版社。

《计算机网络》 吴功宜编著 清华大学出版社

C程序设计(第三版)》 谭浩强著 清华大学出版社


TAG: 程序 文件 局域网 传输

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)