流式套接字如何从服务器发送文件,基于流式套接字实现点到点文件传输

#include "stdio.h"

#include "WinSock2.h"

#pragma comment(lib,"Ws2_32.lib")

const int

MYPORT=20000; //服务器监听的端口号

const int

QLEN=5; //监听队列的长度

const int

BUFLEN=1000; //缓冲区的大小

const int

FNLEN=200; //文件名的最大长度

int main()

{

SOCKET listenSock; //监听套接字

SOCKET

clientSock; //接受客户接入的套接字

struct sockaddr_in

saddr; //本机地址(服务器地址)

struct sockaddr_in

daddr; //对方地址(客户方地址)

char

buf[BUFLEN]; //缓冲区

char

filename[FNLEN]; //要传输到客户端的文件的文件名

char *p;

int

n; //接收到的数据长度

int

fnlen; //文件名的长度

int

aLen; //套接字地址长度

long

code; //响应码

FILE

*fp; //指向要发送给客户端的文件的文件指针

//  初始化WinSock

WORD

wVersionRequested;

WSADATA wsaData;

wVersionRequested=MAKEWORD(1,1);

if(WSAStartup(wVersionRequested,&wsaData))

{

printf("Start Socket

Error!\n");

return 1;

}

//  创建监听套接字,并进入到等待客户接入的状态

memset(&saddr,0,sizeof(struct

sockaddr_in));

saddr.sin_family=AF_INET;

saddr.sin_port=htons(MYPORT);

saddr.sin_addr.s_addr=htonl(INADDR_ANY); if((listenSock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)

{

printf("不能创建套接字!\n");

return 2;

}

if(bind(listenSock,(struct sockaddr

*)&saddr,sizeof(struct

sockaddr_in))==SOCKET_ERROR)

{

printf("绑定套接字错误!\n");

return 3;

}

if(listen(listenSock,QLEN)==SOCKET_ERROR)

{

printf("监听套接字错误!\n");

return 4;

}

else

{

printf("服务器开启,等待客户接入...\n");

}

while(true){

//  接受客户的接入

aLen=sizeof(struct sockaddr_in);

if((clientSock=accept(listenSock,(struct sockaddr

*)&daddr,&aLen))==INVALID_SOCKET)

{

printf("接受客户接入错误!\n");

return 5;

}

printf("客户接入:%s\n",inet_ntoa(daddr.sin_addr));

//  接收客户方欲获取文件的文件名,产生并发送响应码

memset(filename,0,FNLEN);

p=(char *)&fnlen;

recv(clientSock,p,sizeof(fnlen),0); //接收文件名的长度值

fnlen=ntohs(fnlen); //网络字节序转换为主机字节序

p=filename;

recv(clientSock,p,fnlen,0); //接收文件名

printf("客户方想要获取的文件是:%s\n",filename);

if((fp=fopen(filename,"rb"))==NULL) //指定的文件是否存在

{ //指定文件不存在

printf("不能打开指定的文件!\n");

code=htonl(-1); //主要字节序到网络字节序,-1表示出错

p=(char

*)&code;

send(clientSock,p,sizeof(long),0); //发送响应码

closesocket(clientSock); //关闭响应套接字

continue; //回到循环开始,处理下一个客户的请求

}

fseek(fp,0,SEEK_END); //读写指针移动到文件结尾

code=htonl(ftell(fp)); //返回当前读写指针的位置,即得到文件长度。

p=(char *)&code;

send(clientSock,p,sizeof(long),0);

//发送文件长度给客户方

//  打开文件,并把文件内容发送到客户方,然后关闭文件和套接字

rewind(fp); //文件读写指针移动到文件开头

while(!feof(fp)) //文件未结束

{

memset(buf,0,BUFLEN); //清除缓存中的内容

n=fread(buf,1,BUFLEN,fp); //读取文件内容到缓存

send(clientSock,buf,n,0); //把文件内容发送给客户方

}

fclose(fp); //关闭文件

closesocket(clientSock); //关闭连接套接字

}

closesocket(listenSock); //关闭监听套接字

WSACleanup(); //注销WinSock

return 0;

}

#include

#include

"WinSock2.h" //Winsock的头文件

#pragma comment(lib,"Ws2_32.lib") //WINSOCK库

const int

MYPORT=20000; //服务器监听的端口号

const int

BUFLEN=1000; //缓冲区的大小

const int

IPLEN=16; //点分十进制形式IP地址的最大长度

const int

FNLEN=200; //文件名的最大长度

int main()

{

SOCKET

Sock; //套接字描述符

struct sockaddr_in

daddr; //远程服务器地址(daddr)

char

buf[BUFLEN]; //接收缓冲区

char

sIP[IPLEN]; //存储点分十进制形式的IP地址

char

lofile[FNLEN]; //存储本地文件路径和文件名

char

refile[FNLEN]; //远程主机上的文件路径和文件名

char *p;

int

n; //接收到数据的长度

int

aLen; //struct

sockaddr的长度

int

fnlen; //文件长度

long

code; //返回码。小于0:出错,大于0:文件的长度

FILE

*fp; //指向本地文件的指针

//

初始化WinSock。只有在Windows操作系统下,基于WINSOCK编程时需要。

WORD

wVersionRequested;

WSADATA wsaData;

wVersionRequested=MAKEWORD(1,1);

if(WSAStartup(wVersionRequested,&wsaData))

{

printf("Start Socket

Error!\n");

return 1;

}

//  输入服务器的IP地址、欲获取文件的路径名(路径+文件名)、保存到本地的路径名。

memset(sIP,0,IPLEN);

printf("输入服务器的IP地址:");

scanf("%s",sIP);

daddr.sin_family=AF_INET;

daddr.sin_port=htons(MYPORT);

daddr.sin_addr.s_addr=inet_addr(sIP);

aLen=sizeof(struct sockaddr_in);

//  创建套接字并连接到服务器上

if((Sock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)

{

printf("创建套接字错误!\n");

return 2;

}

if(connect(Sock,(struct

sockaddr *)&daddr,aLen)==SOCKET_ERROR)

{

printf("不能连接到服务器!\n");

return 4;

}

else

{

printf("连接服务器成功,可以开始获取文件\n");

}

//连上服务器后输入获取的文件名

memset(refile,0,FNLEN);

printf("输入远程文件名:");

scanf("%s",refile);

memset(lofile,0,FNLEN);

printf("输入本地文件名:");

scanf("%s",lofile);

if((fp=fopen(lofile,"rb"))!=NULL) //本地文件是否存在

{

printf("指定的本地文件已存在!\n");

fclose(fp);

return 1;

}

//  发送远程文件名到服务器

fnlen=htons(strlen(refile)); //文件名长度

p=(char

*)&fnlen; //p指向存储文件名长度变量

send(Sock,p,sizeof(fnlen),0); //发送文件名的长度

send(Sock,refile,strlen(refile),0); //发送文件名

//  接收服务器的响应,并判断是否存在指定的远程文件,若远程文件存在,则显示文件长度

p=(char *)&code;

n=recv(Sock,p,sizeof(long),0);

code=ntohl(code); //网络字节转换为主机字节序

if(code<0) //出错

{

printf("不能打开远程文件!\n");

closesocket(Sock);

return 5;

}

//  接收数据并写入本地文件中

if((fp=fopen(lofile,"wb"))==NULL) //打开本地文件

{

printf("创建文件错误!\n");

return 6;

}

while((n=recv(Sock,buf,BUFLEN,0))>0) //接收数据并写入本地文件中

fwrite(buf,1,n,fp);

fclose(fp); //

closesocket(Sock); //关闭套接字

WSACleanup(); //注销WinSock库

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值