使用TCP服务器搭建简易服务器和客户端,实现文件传输,直接上代码
tcp_server.c
/*===============================================
* 文件名称:tcp_server.c
* 创 建 者:ITLittleDragon
* 描 述:文本传输服务器
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <dirent.h>
#define SIZE 64
int init_server(char *ipaddr, unsigned short port, int backlog)
{
int sockfd = socket(AF_INET,SOCK_STREAM, 0 );//创建通信节点
if(-1 == sockfd)
{
perror("socket");
return -1;
}
struct sockaddr_in saddr;//服务器的地址结构
bzero(&saddr,sizeof(saddr));
saddr.sin_family = AF_INET;//ipv4协议
saddr.sin_port = htons(port);//5001~65535 端口号:主机字节序 -> 网络字节序
saddr.sin_addr.s_addr = inet_addr(ipaddr);//ip地址:点分式 -> 二进制无符号网络字节序
socklen_t slen = sizeof(saddr);
int ret = bind(sockfd, (struct sockaddr *)&saddr,slen);//将服务器自己的ip地址和端口号与sockfd绑定
if(-1 == ret)
{
perror("bind");
close(sockfd);
return -1;
}
ret = listen(sockfd, backlog);//监听是否有客户端请求 sockfd变为监听套接字
if(-1 == ret)
{
perror("listen");
close(sockfd);
return -1;
}
return sockfd;
}
void processList(int rws)//list
{
char buf[SIZE] = {0};
DIR *dp = opendir(".");
if(NULL == dp)
{
perror("opendir");
return ;
}
struct dirent *p = NULL;
while((p=readdir(dp)) != NULL)
{
if(!strcmp(p->d_name,".") || !(strcmp(p->d_name, "..")))
continue;
strcpy(buf, p->d_name);
send(rws, buf, sizeof(buf),0);
}
closedir(dp);
close(rws);
return;
}
void processPut(int rws, char *filename)
{
char buf[SIZE] = {0};
int ret = 0;
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if(-1 == fd)
{
perror("open");
return ;
}
while((ret = recv(rws, buf, sizeof(buf),0)) > 0)//循环接收文件内容
{
write(fd, buf, ret);
}
close(fd);
close(rws);
return;
}
void processGet(int rws, char *filename)
{
char buf[SIZE] = {0};
int ret = 0;
int fd = open(filename, O_RDONLY);
if(-1 == fd)
{
buf[0] = 'N';
send(rws, buf, sizeof(buf), 0);//文件不存在
perror("open");
return ;
}
buf[0] = 'Y';
if(-1 == send(rws, buf, sizeof(buf), 0))//文件存在
{
perror("send");
close(rws);
close(fd);
return ;
}
bzero(buf, sizeof(buf));
while((ret = read(fd, buf, sizeof(buf))) > 0)//循环读取文件内容
{
send(rws, buf, ret,0);
}
close(fd);
close(rws);
return;
}
int main()
{
int sockfd = init_server("0.0.0.0",8888,1024);
if(-1 == sockfd)
{
printf("init_server error\n");
return -1;
}
printf("listen....\n");
char buf[SIZE] = {0};
int ret;
while(1)
{
struct sockaddr_in caddr;//客户端的地址结构
bzero(&caddr, sizeof(caddr));
socklen_t clen = sizeof(caddr);
int rws = accept(sockfd, (struct sockaddr *)&caddr, &clen);//阻塞等待客户端连接
if(-1 == rws)
{
perror("accept");
close(sockfd);
return -1;
}
printf("%s : %u\n",inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));//打印客户端的ip和port
bzero(buf, sizeof(buf));
ret = recv(rws,buf,sizeof(buf),0);//读客户端发送的消息
if(-1 == ret)
{
perror("recv");
break;
}
else if(0 == ret)//客户端关闭
{
printf("client closed\n");
break;
}
switch(buf[0])
{
case 'L'://list
processList(rws);
break;
case 'P'://put
processPut(rws, buf+1);
break;
case 'G'://get
processGet(rws, buf+1);
break;
}
}
close(sockfd);
return 0;
}
tcp_client.c
/*===============================================
* 文件名称:tcp_server.c
* 创 建 者:ITLittleDragon
* 描 述:文本传输客户端
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#define SIZE 64
void processHelp(void)
{
printf("help : print help info\n");
printf("list : display list info on server\n");
printf("put <filename> : put file to server\n");
printf("get <filename> : get file from server\n");
}
void processList(struct sockaddr_in saddr)
{
char buf[SIZE] = {0};
int sockfd = socket(AF_INET,SOCK_STREAM, 0 );//创建通信节点
if(-1 == sockfd)
{
perror("socket");
return ;
}
int ret = connect(sockfd, (struct sockaddr *)&saddr,sizeof(saddr));//连接服务器
if(-1 == ret)
{
perror("connect");
close(sockfd);
return ;
}
//发送请求协议 -> 'L'
buf[0] = 'L';
ret = send(sockfd, buf, sizeof(buf),0);
if(-1 == ret)
{
perror("send");
return ;
}
//循环接收服务器目录文件对应的文件名
while((ret=recv(sockfd, buf,sizeof(buf),0)))
printf("%s ", buf);
printf("\n");
close(sockfd);
}
void processPut(struct sockaddr_in saddr, char *filename)
{
char buf[SIZE] ={0};
int sockfd = socket(AF_INET,SOCK_STREAM, 0 );//创建通信节点
if(-1 == sockfd)
{
perror("socket");
return ;
}
int ret = connect(sockfd, (struct sockaddr *)&saddr,sizeof(saddr));//连接服务器
if(-1 == ret)
{
perror("connect");
close(sockfd);
return ;
}
//P1.c
sprintf(buf, "P%s",filename);
ret = send(sockfd, buf, sizeof(buf),0);//发送请求P1.c
if(-1 == ret)
{
perror("send");
return;
}
int fd = open(filename,O_RDONLY);//打开filename
if(-1 == fd)
{
perror("open");
return;
}
bzero(buf,sizeof(buf));
while((ret=read(fd, buf, sizeof(buf))) > 0)//循环读取文件内容
{
send(sockfd, buf, ret,0);//将文件内容发送给服务器
}
close(fd);
close(sockfd);
return;
}
void processGet(struct sockaddr_in saddr,char *filename)
{
char buf[SIZE] = {0};
int sockfd = socket(AF_INET,SOCK_STREAM, 0 );//创建通信节点
if(-1 == sockfd)
{
perror("socket");
return ;
}
int ret = connect(sockfd, (struct sockaddr *)&saddr,sizeof(saddr));//连接服务器
if(-1 == ret)
{
perror("connect");
close(sockfd);
return ;
}
//eg: G1.c
sprintf(buf, "G%s",filename);
ret = send(sockfd, buf, sizeof(buf),0);//发送请求G1.c
if(-1 == ret)
{
perror("send");
close(sockfd);
return;
}
if(-1 == recv(sockfd, buf, sizeof(buf), 0))//读服务器的响应 'N':没有此文件 'Y':有文件
{
perror("recv");
close(sockfd);
return ;
}
if(buf[0] == 'N')
{
printf("No such file\n");
close(sockfd);
return ;
}
int fd = open(filename,O_WRONLY | O_CREAT | O_TRUNC, 0777);//打开filename
if(-1 == fd)
{
perror("open");
return;
}
bzero(buf,sizeof(buf));
while((ret=recv(sockfd, buf, sizeof(buf),0)) > 0)//循环接收服务器发送的文件内容
{
write(fd, buf, ret);//将接收的文件内容写入文件fd
}
close(fd);
close(sockfd);
return ;
}
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM, 0 );//创建通信节点
if(-1 == sockfd)
{
perror("socket");
return -1;
}
printf("sockfd=%d\n",sockfd);
struct sockaddr_in saddr;//服务器的地址结构
bzero(&saddr,sizeof(saddr));
saddr.sin_family = AF_INET;//ipv4协议
saddr.sin_port = htons(8888);//5001~65535 端口号:主机字节序 -> 网络字节序
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址:点分式 -> 二进制无符号网络字节序
socklen_t slen = sizeof(saddr);
char buf[SIZE] = {0};
while(1)
{
printf("<client>");
bzero(buf, sizeof(buf));
fgets(buf,sizeof(buf)-1, stdin);
buf[strlen(buf)-1] = '\0';
if(strncmp(buf, "help",4) == 0)
{
processHelp();
}
else if(strncmp(buf,"list",4) == 0)//list
{
processList(saddr);
}
else if(strncmp(buf,"put ", 4) == 0) //put
{
processPut(saddr, buf+4);
}
else if(strncmp(buf,"get ", 4) == 0) //get
{
processGet(saddr, buf+4);
}
else
{
printf("Bye ~\n");
break;
}
}
close(sockfd);
return 0;
}