/**************************************************************************************
修改 IP
把服务器端保存为:socket_service.c 客户端:socket_client.c
地址和端口号,即可实现任意主机互联, 传送文件的大小和格式没有限制!
编译时执行:
gcc -g socket_service.c -lpthread -o server
gcc -g socket_client.c -o client
端执行 : #./server
在 server
client
端执行: #./client ./baby.jpg MyBaby.jpg
或者: #./client Linux_driver.pdf MyFile.pdf
第一个参数是:client
要发送的文件, 第二个参数是 :server 要保存的文件名。
即可把 client 端当前目录下的 Linux_driver.pdf 发送给 server
己定义。
但不能太长, 可以去修改 data.h
中的 struct data
中的 filename ,filesavename 。
端, 保存名为 Myfile.pdf, 路径可以自
由于 网络接口 MTU 的限制(一般 mtu 为 1500),大些的文件只能分多次发送,这样就有几个问题:
分几次发送?一次发送多大? 保存端的怎么保存?
这些问题在我的代码中都得到了解决, 而且 server
接收端!
经过测试, 下面的代码没有严重的 bug, 一次性传送几个 M 的文件轻松愉快,而且各种反馈信息保证了调试,
修改非常容易!
端采用了多线程处理, 理论上说,这是一个非常强悍的
欢迎大家给以批评指正!
All the code wirten by
韩大卫 @吉林师范大学
*************************************************************************************/
/*******socket_service.c***************************/
#include "data.h"
int sockid;
pthread_t tid;
int fileopen;
__sighandler_t f_quit(void)
{
printf("\nserver closed right now!!\n");
close(sockid);
close(fileopen);
exit(0);
}
struct thread_para{
int sockid;
struct sockaddr_in addr;
struct sockaddr_in fromaddr;
struct data datarecv;
};
int main(int argc,char* argv[])
{
signal(SIGINT,(__sighandler_t)f_quit);
struct thread_para thread_do;
memset(&thread_do,0,sizeof(thread_do));
sockid = socket(AF_INET,SOCK_STREAM,0);
if(sockid == -1)
printf("socker create error!"),exit(-1);
printf("sockid = %d\n",sockid);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
//inet_aton("192.168.10.50",&addr.sin_addr);
addr.sin_addr.s_addr = INADDR_ANY;
int r = bind(sockid,(struct sockaddr*)&addr,sizeof(addr));
if(r<0)
printf("bind error!,r=%s\n",strerror(errno)),exit(-1);
printf("bind success!\n");
if((r = listen(sockid,10))<0)
printf("listen error!,r=%s\n",strerror(errno)),exit(-1);
printf("listen successfully!\n");
int fd,writelen,writelencount,recvlen,opnumber;
struct sockaddr_in fromaddr;
socklen_t len = sizeof(fromaddr);
void* handler(void*);
while(1){
if( (fd = accept(sockid,(struct sockaddr*)&fromaddr,&len)) < 0 ){
printf("accept error,errno = %s\n",strerror(errno)),exit(-1);
}
printf("accept successfuluy!,new sockid=%d\n",fd);
memset(&thread_do,0,sizeof(thread_do));
thread_do.sockid = fd;
thread_do.fromaddr = fromaddr;
pthread_create(&tid,NULL,handler,&thread_do);
}
}
void* handler(void* p)
{
struct thread_para * thread_do = p;
int writelen,writelencount,recvlen,opnumber;
writelen = 0;
writelencount = 0;
recvlen = 0;
opnumber = 1;
printf(" there are the data from %s :\n",inet_ntoa(thread_do->fromaddr.sin_addr) );
do{
memset(&thread_do->datarecv,0,sizeof(thread_do->datarecv));
recvlen = recv( thread_do->sockid,&thread_do->datarecv,sizeof(thread_do->datarecv)-1,
0);
if(recvlen<0) printf("recv error!,errro=%s\n",strerror(errno)),exit(-1);
else if(recvlen == 0 )
printf(" client has closed!\n");
else
printf("the filename from client:\n\t%s\n",thread_do->datarecv.filename);
printf("the file save name:\n\t%s\n",thread_do->datarecv.filesavename);
printf("the filelen =%d,the recvlen=%d,the filebuf = %d\n",thread_do->datarecv.filelen,
recvlen,sizeof(thread_do->datarecv.filebuf)-1 );
printf("the shouldoplen = %d\n",thread_do->datarecv.shouldoplen);
printf("the oplencount = %d\n",thread_do->datarecv.oplencount);
umask(0);
int fileopen = open((const char*)thread_do->datarecv.filesavename,O_RDWR | O_CREA
T | O_APPEND, S_IRWXU | S_IRWXG | S_IROTH );
if(fileopen<0){
printf("fileopen error!,%s\n",strerror(errno)),exit(-1);
}
printf("file %s create and open successfully!\n",thread_do->datarecv.filesavename);
if( ( writelen = write(fileopen,thread_do->datarecv.filebuf,thread_do->datarecv.shoul
doplen) ) <0 ){
printf("write error!\n"),exit(-1);
}
ritelencount);
writelencount += writelen;
printf(" opnumber = %d,writelen=%d,writelencount=%d\n \n",opnumber++,writelen,w
struct data_return data_r;
data_r.writelen = writelen;
data_r.writelencount = writelencount;
data_r.recvlen = recvlen;
write(thread_do->sockid, &data_r ,sizeof(data_r));
close(fileopen);
}while( writelencount != thread_do->datarecv.filelen );
}
/**************************************************************************************/
/*************socket_client.c**************************/
#include "data.h"
int sockid;
__sighandler_t f_quit(void)
{
printf("\n client closed right now!!\n");
close(sockid);
exit(0);
}
void delay()
{
int i ,j;
for(i = 0;i<1000;i++)
for(j=0;j<120000;j++);
}
int main(int argc,char* argv[])
{
signal(SIGINT,(__sighandler_t)f_quit);
sockid = socket(AF_INET,SOCK_STREAM,0);
if(sockid==-1)printf("socket create error!"),exit(-1);
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
inet_aton("192.168.10.53",&addr.sin_addr);
int r = connect(sockid,(struct sockaddr*)&addr,sizeof(addr));
if(r<0)printf("connect error!\n"),exit(-1);
printf("connect success! \n");
struct data datasent;
memset(&datasent,0,sizeof(datasent));
struct data_return data_r;
memset(&data_r,0,sizeof(data_r));
strcpy(datasent.filename, argv[1]);
strcpy(datasent.filesavename,argv[2]);
int fd = open(datasent.filename,O_RDWR);
if(fd<0)printf("open %s failed!\n",datasent.filename),exit(-1);
datasent.filelen = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
printf("open file %s success!,the fd = %d,file length = %d\n",datasent.filename,fd,datasen
t.filelen);
datasent.oplencount = 0;
int opnumber = 1;
do{
lseek(fd,datasent.oplencount,SEEK_SET);
if( (datasent.filelen - datasent.oplencount ) >= ( sizeof(datasent.filebuf) - 1 ) ){
datasent.shouldoplen = datasent.filelen -datasent.oplencount;
datasent.shouldoplen = sizeof(datasent.filebuf) - 1 ;
}
else{
}
memset(&datasent.filebuf,0,sizeof(datasent.filebuf));
readdata(fd,&datasent,datasent.shouldoplen);
datasent.oplencount += datasent.shouldoplen;
sentdata(datasent);
printf(" opnumber = %d,shouldoplen = %d ,datasent.oplencount = %d \n",opnumber++,da
tasent.shouldoplen,datasent.oplencount);
read(sockid,&data_r,sizeof(data_r));
printf("server info:recvlen = %d, writelen = %d, writelencount = %d \n\n",data_r.recvlen,da
ta_r.writelen,data_r.writelencount);
//
delay();
} while( datasent.filelen > datasent.oplencount );
close(sockid);
close(fd);
}
int readdata(int fd,struct data* datasent,int len)
{
int readlen;
if((readlen = read( fd,datasent->filebuf,len ) )<0)
printf("%m\n"),exit(-1);
printf("read %s successfully ! readlen=%d\n",datasent->filename,readlen);
//printf("%s\n",datasent->filebuf);
}
int sentdata(struct data datasent)
{
int sendlen;
if((sendlen = send( sockid,&datasent,sizeof(datasent)-1,0 ))<0){
sent), strerror(errno));
printf("write error ,writelen=%d, sizeof(datasent): %d, error: %s\n",sendlen, sizeof(data
exit(-1);
}
printf("file %s send successfully!,sendlen=%d\n",datasent.filename,sendlen);
}
/*************************************************************************************/
/***********data.h*********************************/
#ifndef DATA_H
#define DATA_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "data.h"
typedef unsigned int uint;
struct data{
char filename[30];
char filesavename[30];
uint filelen;
uint shouldoplen;
uint oplencount;
char filebuf[1301];
};
struct data_return {
int writelen;
int writelencount;
int recvlen;
};