原文是在
http://bbs.chinaunix.net/viewthread.php?tid=57032
上发布的(好像这个地址的也是转载^_^)
不过文章中提供的源代码问题确实太多了,昨天一位网友求助让我帮其调试程序,一看,想不到竟是这片文章提供的代码,而且自己还回过贴,呵呵,真是有缘,晚上便将代码调试了一下,顺便做了些格式上的修改,相信大概的思想大家都已经明白了,今天早上调通了试了试还不错,传了个图片和应用程序,蛮快的,贴出来与大家分享一下:
(1):首先在/etc/host中添加Server地址,我的机上是这样
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost
可以随便改成你喜欢的名字,阿毛阿狗都可以,只要跟后面程序中的host_name中一致就行了
下面贴出代码
服务器端,也就是文件存放端的程序
//Author: May be duanjigang, ^_^
#include<stdio.h>
#include<sys/types.h>
#include<sys/fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#define command "clear"
//这里其实应改写成ifdef _WIN32 define command "cls" else define "clear",更合理些
#include<errno.h>
#define big_size 2048
#define small_size 50
int main(void)
{
char c= 0,
buf[big_size],//读文件的缓冲
file[small_size],//文件名
host_name[small_size];//主机名
int fromlen = 0,source = 0;
register int k,s,ns;
struct sockaddr_in sin;
struct hostent * hp;
system(command);//清屏
printf("输入要传输的文件名:");
memset(file, 0, small_size);
scanf("%s",file);
if ((source = open(file, O_RDONLY) ) < 0)
{
perror("源文件打开出错");
exit(1);
}
memset(host_name, 0, small_size);
//写入server的名子,然后gethostbyname将会根据这个名子去找主机的信息
sprintf(host_name, "%s", "Server");
if((hp = gethostbyname(host_name)) == NULL)
{
perror("返回主机地址信息错!!!");
exit(2);
}
if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("获取SOCKET号失败!!!");
exit(3);
}
sin.sin_family=AF_INET;
sin.sin_port=htons(1500);
memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0 )
{
printf("不能将服务器地址捆绑到SOCKET号上!!!\n");
close(s);
exit(4);
}
if(listen(s,5) < 0)
{
fprintf(stderr, "sever:listen\n");
exit(5);
}
while(1)
{
printf("等待传送文件中.......\n");
if((ns = accept(s, NULL, NULL)) < 0 )
{
fprintf(stderr, "sever:accept\n");
exit(6);
}
lseek(source,0L,0);
printf("开始传送文件.....\n");
//先把文件名发过求
write(ns,file,sizeof(file));
printf("%s\n", file);
//发送文件名
memset(buf, 0, big_size);
while( (k = read(source, buf, sizeof(buf))) > 0)
{
//循环发送直到,文件结束
write(ns,buf,k);
memset(buf, 0, big_size);
}
printf("\n传输完毕\n");
close(ns);
}
close(source);
exit(0);
}
[code]
客户端,即要下载文件的机子端程序
[code]
/*****************************FileClient.c********************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#define command "clear"
#include<errno.h>
#include <string.h>
#define big_size 1024
#define small_size 50
int main(void)
{
char buf[big_size] ={0},file[small_size]={0},
host_name[small_size]={0};
int target,ret;
register int bytes,sockfd;
struct sockaddr_in sin ;
struct hostent *hp;
system(command);
sprintf(host_name, "%s", "Server");
if((hp = gethostbyname(host_name)) == NULL)
{
fprintf(stderr, "返回服务器地址信息错!!!\n");
exit(1);
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0)
{
fprintf(stderr, "获取SOCKET号失败!!!\n");
exit(2);
}
memset((char*)&sin, '\0', sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(1500);
sin.sin_addr = *(struct in_addr*)hp->h_addr;
if((ret = connect(sockfd, (struct sockaddr*)&sin, sizeof(sin))) == -1)
{
fprintf(stderr, "不能与服务器连接!!!\n");
exit(3);
}
memset(buf, 0, big_size);
while(read(sockfd, file, sizeof(file)) < 0);
sprintf(buf, "%s_%s", "receive", file);
if((target=open(buf, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
{
perror("不能打开目标文件!!");
exit(4);
}
memset(buf, 0, big_size);
while((bytes = read(sockfd, buf, sizeof(buf))) > 0)
{
write(target,buf,bytes);
memset(buf, 0, big_size);
}
printf("接收文件成功!!!\n");
close(sockfd);
close(target);
}
(1):实现windows和Linux的多平台程序,昨天在windows下调通了,可是客户端老是出错,就没做太多研究,有兴趣的朋友可以尝试一下。
(2):今天忽然想到,既然都做到这个地步了,我们为何不把它作成一个FTP程序,而且,考虑到多客户串行端传输比较费时,所以最好在accept到一个客户端的时候就生成一个线程,实现并行下载,对于FTP我也不是很懂,不过觉的这样应改可以实现吧,后面有空了一定要尝试的,在此先提一下自己的想法,有兴趣的朋友可以自己实现一下,呵呵,最近太忙了,都没时间光顾CU了,学习,学习。。。。。。。。








