当前位置:文档之家› TCPIP编程实现远程文件传输详解(含代码解析)

TCPIP编程实现远程文件传输详解(含代码解析)


#include <sys/socket.h>
int bind(int socketfd,strUCt sockaddr_in *localaddr,sizeof(localaddr));
其中:(1)第一个参数 socketfd 是前步 socket()系统调用返回的套节字描述符。
(2)第二个参数被捆向本地地址的一种结构,该结构在 sys/netinet/in.h 中定义:
printf(″输入要传输的文件名:″); scanf(″%s″,file); if ((source=open(file,O_RDONLY))<0){
perror(″源文件打开出错″); exit(1); } printf(″ 在传送文件,稍候…″); hp=gethostbyname(″server″); if (hp==NULL){ perror(″返回主机地址信息错!!!″); exit(2); } s=socket(AF_INET,SOCK_STREAM,0); if(s<0){ perror(″获取 SOCKET 号失败!!!″); exit(3);
while((k=read(source,buf,sizeof(buf)))>0) write(ns,buf,k); printf(″
传输完毕!!! ″);
close(ns); }
close(source); exit(0); /*客户机源程序 khj.c*/ #include >stdio.h> #include >sys/types.h> #include >sys/fcntl.h> #include >sys/socket.h> #include >sys/netinet/in.h> #include >netdb.h> #include >errno.h> #include >string.h> main() {
在 TCP/IP 网络结构中,为了保证网络安全,网络人员往往需要在路由器上添加防火墙,禁止非法用户用 FTP 等安全危害较大的 TCP/IP 协议访问主机。而有时系统维护人员需要用 ftp 将一些文件从中心机房主机 传到前端网点主机上,比如应用程序的替换升级。如果每次传输文件时都要打开防火墙,未免显得有些繁 琐,要是在自己的应用程序中增加一个专门的文件传输模块,那将是十分愉快的事情。
AF_IMPLINK (IMP 链接层)
(2)type 指明套接字类型,取值有:
SOCK_STREAM
(流套接字)
SOCK_DGRAM
(Hale Waihona Puke 据报套接字)SOCK_RAW
(原始套接字)
SOCK_SEQPACKET (定序分组套接字)
一般情况下,前两个参数的组合就可以决定所使用的协议,这时第三个参数被置为 0,如果第一个参
struct sockaddr_in{
short sin_family;/*socket()系统调用的协议族如 AF_INET*/
u_short sin_port;/*网络字节次序形式的端口号码*/
struct in_addr sin_addr;/*网络字节次序形式的网络地址*/
char sin_zero[8];
struct hostent{ char *h_name; char **h_aliases; int h_addrtype; int h_length; /*地址长度*/ char **h_addr_list; #define h_addr h_addr_list[0];/*地址*/ } (3)第三个参数为第二个结构参数的长度,如果调用成功,bind 返回 0,否则将返回-1 并设置 errno。 3.服务器端系统调用 listen,使服务器愿意接受连接 格式:int listen(int socketfd,int backlong) 它通常在 socket 和 bind 调用后在 accept 调用前执行。第二个参数指明在等待服务器执行 accept 调用时 系统可以排队多少个连接要求。此参数常指定为 5,也是目前允许的最大值。 4.服务器调用 accept,以等待客户机调用 connect 进行连接。格式如下: int newsocket=(int socketfd,struct sockaddr_in *peer,int*addrlen); 该调用取得队列上的第一个连接请求并建立一个具有与 sockfd 相同特性的套节字。如果没有等待的连 接请求,此调用阻塞调用者直到一连接请求到达。连接成功后,该调用将用对端的地址结构和地址长度填 充参数 peer 和 addlen,如果对客户端的地址信息不感兴趣,这两个参数用 0 代替。 5.客户端调用 connect()与服务器建立连接。格式为: connect(int socketfd,struct sockaddr_in *servsddr,int addrlen) 客户端取得套接字描述符后,用该调用建立与服务器的连接,参数 socketfd 为 socket()系统调用返回的 套节字描述符,第二和第三个参数是指向目的地址的结构及以字节计量的目的地址的长度(这里目的地址应 为服务器地址)。调用成功返回 0,否则将返回-1 并设置 errno。 6.通过软插座发送数据 一旦建立连接,就可以用系统调用 read 和 write 像普通文件那样向网络上发送和接受数据。Read 接受 三个参数:一个是套节字描述符;一个为数据将被填入的缓冲区,还有一个整数指明要读的字节数,它返 回实际读入的字节数,出错时返回-1,遇到文件尾则返回 0。Write 也接受三个参数:一个是套节字描述 符;一个为指向需要发送数据的缓冲区,还有一个整数指明要写入文件的字节个数,它返回实际写入的字 节数,出错时返回-1。当然,也可以调用 send 和 recv 来对套节字进行读写,其调用与基本的 read 和 write 系统调用相似,只是多了一个发送方式参数。 7.退出程序时,应按正常方式关闭套节字。格式如下: int close(socketfd) 前面介绍了 UNIX 客户/服务器模式网络编程的基本思路和步骤。值得指出的是 socket 编程所涉及的系统调 用不属于基本系统调用范围,其函数原形在 libsocket.a 文件中,因此,在用 cc 命令对原程序进行编译时需 要带-lsocket 选项。 现在,我们可以针对文章开头提出的问题着手进行编程了。在图示的网络结构中,为使中心机房的服 务器能和网点上的客户机进行通信,需在服务器端添加通过路由器 1 1 1 2 到客户机的路由,两台客户 机也必须添加通过路由器 2 2 2 1 到服务器的路由。在服务器的/etc/hosts 文件中应该包含下面内容: 1.1.1.1 server
2.2.2.2 cli1 2.2.2.3 cli2 客户机的/etc/hosts 文件中应该有本机地址信息和服务器的地址信息,如 cli1 客户机的/etc/hosts 文件: 2.2.2.2 cli1 1.1.1.1 server 网络环境搭建好后,我们可以在服务器端编写 fwq.c 程序,负责接受客户机的连接请求,并将从源文 件中读取的数据发送到客户机。客户机程序 khj.c 向服务器发送连接请求,接收从服务器端发来的数据,并 将接收到的数据写入目标文件。源程序如下: /*服务器源程序 fwq.c*/ #include <stdio.h> #include <sys/types.h> #include <sys/fcntl.h> #include <sys/socket.h> #include <sys/netinet/in.h> #include <netdb.h> #include <errno.h> main() { char c,buf[1024],file[30]; int fromlen,source; register int k,s,ns; struct sockaddr_in sin; struct hostent *hp; system(″clear″); printf(″ ″);
UNIX 网络程序设计一般都采用套接字(socket)系统调用。针对目前十分流行的客户/服务器模式,其程
序编写步骤如下:
1.Socket 系统调用
为了进行网络 I/O,服务器和客户机两端的 UNIX 进程要做的第一件事是调用 socket()系统调用,建立
软插座,指明合适的通讯协议。格式为:
#include >sys/types.h>
char buf[1024],file[30]; char *strs=″
正在接收文件″; int target; register int k,s; struct sockaddr_in sin; struct hostent *hp; system(″clear″); printf(″
} sin.sin_family=AF_INET; sin.sin_port=htons(1500);/*使用端口 1500*/ bcopy(hp->h_addr,&sin.sin_addr,hp->h_length); if(bind(s,&sin,sizeof(sin))<0){
perror(″不能将服务器地址捆绑到 SOCKET 号上!!!″); colse(s); exit(4); } if(listen(s,5)<0{ perror(″sever:listen″); exit(5); } while(1){ if((ns=accept(s,&sin,&fromlen))<0){ perror(″sever:accept″); exit(6); } lseek(source,OL,0);/*每次接受客户机连接,应将用于读的源文件指针移到文件头*/ write(ns,file,sizeof(file)); /*发送文件名*/
相关主题