/* 并发服务器模型 */
/* TCP文件服务器代码 */
/* 头文件 */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* 宏定义 */
#define DEFAULT_SVR_PORT 2828
#define FILE_MAX_LEN 64
/* 全局变量区 */
char filename[FILE_MAX_LEN+1];
/* handle_cilent函数 */
static void *handle_cilent(void *arg)
{
int sock = (int)arg;
char buf[1024];
int len,ret;
FILE *fp;
printf("Begin Send!\n");
fp = fopen(filename,"r");
if(NULL == fp)
{
close(sock);
exit(6);
}
/* 发文件名 */
ret = send(sock,filename,FILE_MAX_LEN,0);
if(-1 == ret)
{
perror("Send file name");
goto EXIT_THREAD;
}
printf("Begin send file %s ...\n",filename);
/* 发送文件内容 */
while(!feof(fp))
{
len = fread(buf,1,sizeof(buf),fp);
printf("Sever read %s ,len %d \n",filename,len);
ret = send(sock,buf,len,0);
if(ret < 0)
{
perror("Send file content");
goto EXIT_THREAD;
}
}
EXIT_THREAD:
if(fp)
close(fp);
close(sock);
}
/* main函数 */
int main(int argc , char *argv[])
{
int sockfd,newfd;
int ret;
int sin_size,numbytes;
/* 定义2个IPV4地址 */
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
pthread_t thread;
unsigned short port;
if(argc < 2)
{
printf("Please input a filename without path\n");
exit(1);
}
strncpy(filename,argv[1],FILE_MAX_LEN);
port = DEFAULT_SVR_PORT;
if(argc >= 3)
{
port = (unsigned short)atoi(argv[2]);
}
/* 第一步:建立TCP套接字socket */
/* AF_INET :ip通信 SOCK_STREAM:TCP */
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sockfd)
{
perror("socket");
exit(2);
}
/* 第二步:设置监听端口
功能:初始化结构体,并绑定2828端口 */
memset(&my_addr,0,sizeof(struct sockaddr));
my_addr.sin_family = AF_INET; // IPV4
my_addr.sin_port = htons(port); //设置监听端口为2828,用htons转成网络序
my_addr.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY来表示任意IP地址可能通信
/* 第三步:绑定套接字,把socket队列于端口关联起来 */
ret = bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));
if(-1 == ret)
{
perror("bind error");
goto EXIT_MAIN;
}
/* 第四步:开始在2828端口监听,是否有客户端发来连接 */
ret = listen(sockfd,10);
if(-1 == ret)
{
perror("listen");
goto EXIT_MAIN;
}
printf("Listen Port:%d !\n",port);
/* 循环与客户端通信 */
while(1)
{
sin_size = sizeof(struct sockaddr_in);
printf("\nSever waiting ... \n");
//如果有客户端建立连接,将会产生一个全新的套接字newfd,专门用于和这个客户端通信
newfd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);
if(-1 == newfd)
{
perror("accept");
goto EXIT_MAIN;
}
printf("Cilent (ip = %d : port = %d ) request !\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port));
//生成一个线程来完成与客户端的对话,父进程继续监听
pthread_create(&thread,NULL,handle_cilent,(void *)newfd);
}
/* 第六步:关闭Socket */
EXIT_MAIN:
close(sockfd);
return 0;
}
/* TCP 文件接收客户端 */
#include "Head.h" //自己写的头文件
#define FILE_MAX_LEN 64
#define DEFAULT_SVR_PORT 2828
int main(int argc,char *argv[])
{
int sockfd,ret,total,len;
char ip_addr[64];
unsigned short port;
struct hostent *he;
struct sockaddr_in their_addr;
char filename[FILE_MAX_LEN+1],buf[1024];
FILE *fp ;
if(argc < 2)
{
printf("Need s sever ip!\n");
exit(1);
}
strncpy(ip_addr,argv[1],sizeof(ip_addr));
port = DEFAULT_SVR_PORT;
if(argc >= 3)
{
port = (unsigned short)atoi(argv[2]);
}
/* 域名解析 */
// he = gethostbyname(argv[1]);
/* 第一步: 建立一个TCP套接字 */
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sockfd)
{
perror("sockfd");
exit(2);
}
/* 第二步:设置服务器地址和端口2828 */
memset(&their_addr,0,sizeof(their_addr));
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(port);
their_addr.sin_addr.s_addr = inet_addr(ip_addr);
printf("Conect Sever %s :%d \n",ip_addr,port);
/* 第三步: 用connect 和服务器建立连接,使用协议栈自动分配端口 */
ret = connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr));
if(-1 == ret)
{
perror("connect");
exit(3);
}
ret = send(sockfd,"Hello",6,0);
if(ret < 0)
{
perror("send");
exit(4);
}
/* 接收文件名 */
total = 0;
while(total < FILE_MAX_LEN)
{
//接收的buf长度,始终是未接收的文件名长度剩下的长度
len = recv(sockfd,filename+total,(FILE_MAX_LEN - total),0);
if(len <= 0)
{
break;
}
total += len;
}
/* 接收文件名出错 */
if(total != FILE_MAX_LEN)
{
perror("failure file name");
exit(5);
}
printf("recv file %s ...\n",filename);
fp = fopen(filename,"wb");
if(NULL == fp)
{
perror("open");
exit(6);
}
/* 接收文件数据 */
printf("\nRec File Begin!\n");
total = 0;
while(1)
{
len = recv(sockfd,buf,sizeof(buf),0);
if(-1 == len)
{
break;
}
total += len;
//写入本地文件
fwrite(buf,1,len,fp);
}
fclose(fp);
printf("Recv file %s success! Total length:%d \n",filename,total);
/* 关闭socket */
close(sockfd);
return 0;
}
后记:学而思,思而问,问而后多敲代码