Linux c实现一个tcp文件服务器和客户端
2017-05-20 11:43
411 查看
总体需求:
编写tcp文件服务器和客户端。客户端可以上传和下载文件。
================================================分解需求
客户端功能描述:
1)要求支持以下命令:help: 显示客户端所有命令和说明, 在本地实现即可,help的内容不需要从服务器传回。
list: 显示服务器端可下载文件列表,列表内容需要从服务器端传回。
get <filename>: 根据<filename>下载指定文件,<filename>只包含文件名,如果出现"/"等字符任务是路径,不予支持;下载后的文件存放在当前工作路径下即可。
put <pathname>: 上传文件 <pathname> 必须为客户端本机的合法路径,客户端搜索到文件后推送给服务器
quit: 退出客户端
2)客户端启动后可以反复输入命令,除非用户输入quit才会退出。
3) 每次命令(list/get/put)建立一个连接,命令执行完毕后关闭该连接。
服务器端功能:
1)文件服务器不要求支持并发,同时只支持一个连接,即一个客户端发起的一次命令。一次命令执行完毕后关闭连接并继续等待下一次连接请求。2)文件服务器启动后一直执行,除非被人为强制关闭。
3)文件服务器端需要设定一个目录用于存放所有的文件,该目录路径不支持可配置,且该目录不要求再包含子目录。称其为"文件存放目录"。
4)对list服务,服务器端从"文件存放目录"下列举出所有的文件名称并发送给客户端。
5)对get服务,服务器根据用户指定的文件名缺省从"文件存放目录"搜索该文件并推送文件到客户端,推送不会删除原服务器上的文件。
6)对put服务,服务器将用户推送的文件存储到"文件存放目录",如果存在同名的文件则拒绝。
7)若执行命令和传输过程中发生错误,关闭当前连接并进入等待下一个连接。
=================================================
提示:
请在编码前仔细设计一个简单的应用层协议规定客户端和服务器端之间命令传输的请求和应答流程和格式。
二。参考代码:
1.服务器端参考代码
[cpp] view plain copy#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<dirent.h>
#include<errno.h>
#define N 128
#define PORT_NUM 8888
typedef struct sockaddr SA;
void ProcessList(int connfd)
{
char buf
;
DIR *mydir;
struct dirent *myitem;
mydir = opendir(".");
while((myitem = readdir(mydir)) != NULL){
if((strcmp(myitem->d_name, ".") == 0) || (strcmp(myitem->d_name, "..") == 0))
continue;
strcpy(buf, myitem->d_name);
send( connfd, buf, N, 0);
}
close(connfd);
return;
}
void ProcessGet(int connfd, char buf[])
{
int fd,nbyte;
if(( fd = open(buf+1, O_RDONLY)) < 0){
fprintf(stderr, "fail to open %s: %s\n",buf+1,strerror(errno));
buf[0] = 'N';
send(connfd, buf, N, 0);
return;
}
buf[0] = 'Y';
send(connfd, buf, N, 0);
while(( nbyte = read( fd, buf, N)) > 0){
send(connfd, buf, nbyte, 0);
}
close(connfd);
return;
}
void ProcessPut(int connfd, char buf[])
{
int fd, nbyte;
if(( fd = open(buf+1, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0){
printf("fail to create %s on server\n",buf+1);
return;
}
while(( nbyte = recv( connfd, buf, N, 0)) > 0){
write(fd, buf, nbyte);
}
close(fd);
return;
}
int main(int argc, char *argv[])
{
int listenfd, connfd;
int optval = 1;
char buf
;
struct sockaddr_in server_addr;
if(( listenfd = socket( AF_INET, SOCK_STREAM, 0)) < 0 ){
fprintf(stderr, "fail to socket: %s\n",strerror(errno));
exit(-1);
}
#ifdef _DEBUG_
printf("socket is %d\n", listenfd);
#endif
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUM);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if( bind( listenfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
perror("fail to bind");
exit(-1);
}
listen( listenfd, 5);
while(1){
if(( connfd = accept(listenfd, NULL, NULL)) < 0){
perror("fail to accept");
break;
}
recv( connfd, buf, N, 0);
switch(buf[0]){
case 'L': ProcessList(connfd);
break;
case 'G': ProcessGet(connfd, buf);
break;
case 'P': ProcessPut(connfd, buf);
break;
default: printf("Input ");
}
close(connfd);
}
return 0;
}
2.客户端参考代码:
[cpp] view plain copy#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define N 128
#define PORT_NUM 8888
typedef struct sockaddr SA;
void PrintHelp()
{
printf("help: display help info\n");
printf("list: get file list of server\n");
printf("get : get <file>\n");
printf("put : put <file>\n");
printf("quit: quit the client\n");
return;
}
void ProcessList(struct sockaddr_in server_addr)
{
int sockfd, nbyte;
char buf
;
if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
printf("fail to list\n");
return;
}
if( connect(sockfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
printf("fail to connect server\n");
goto ERROR_1;
}
strcpy(buf, "L");
send(sockfd, buf, N, 0);
while(( nbyte = recv( sockfd, buf, N, 0)) != 0){
printf("%s\n",buf);
}
ERROR_1:
close(sockfd);
return;
}
void ProcessGet(struct sockaddr_in server_addr, char command[])
{
int sockfd, nbyte, fd;
char buf
;
if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
printf("fail to get\n");
return;
}
if( connect( sockfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
printf("fail to connect server\n");
goto ERROR_2;
}
sprintf(buf, "G%s", command+4);
send(sockfd, buf, N, 0);
recv(sockfd, buf, N, 0);
if(buf[0] == 'N'){
printf("No such file on server\n");
goto ERROR_2;
}
if(( fd = open(command+4, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0){
printf("fail to create local file %s\n",command+4);
goto ERROR_2;
}
while(( nbyte = recv(sockfd, buf, N, 0)) > 0){
write(fd, buf, nbyte);
}
close(fd);
ERROR_2:
close(sockfd);
return;
}
void ProcessPut(struct sockaddr_in server_addr, char command[])
{
int sockfd, fd, nbyte;
char buf
;
if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
printf("fail to get\n");
return;
}
if( connect(sockfd,(SA *)(&server_addr),sizeof(server_addr)) < 0){
printf("fail to connect server\n");
goto ERROR_3;
}
if((fd = open(command+4, O_RDONLY)) < 0){
printf("fail to open %s\n",command+4);
goto ERROR_3;
}
sprintf(buf, "P%s", command+4);
send(sockfd, buf, N, 0);
while(( nbyte = read(fd, buf, N)) > 0){
send(sockfd, buf, nbyte, 0);
}
close(fd);
ERROR_3:
close(sockfd);
return;
}
int main(int argc, char *argv[])
{
int sockfd, fd, nbyte;
char command[32];
struct sockaddr_in server_addr;
if(argc < 3){
printf("Usage: %s <server_ip> <port>\n",argv[0]);
exit(-1);
}
if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
fprintf(stderr, "fail to socket: %s\n", strerror(errno));
exit(-1);
}
#ifdef _DEBUG_
printf("socket is %d\n",sockfd);
#endif
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
//server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
printf("<client>");
fgets(command, 32, stdin);
command[strlen(command)-1] = '\0';
if(strcmp( command, "help") == 0){
PrintHelp();
}
else if(strcmp( command, "list") == 0){
ProcessList(server_addr);
}
else if(strncmp( command, "get", 3) == 0){
ProcessGet(server_addr, command);
}
else if(strncmp( command, "put", 3) == 0){
ProcessPut(server_addr, command);
}
else if(strcmp( command, "quit") == 0){
printf("Bye\n");
break;
}
else{
printf("Wrong command, 'help' for command list.\n");
}
}
return 0;
}
3.验证结果(ubuntu14.04)
相关文章推荐
- Linux c实现一个tcp文件服务器和客户端
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器 <转>
- 用 TCP 协议写一个客户端和一个服务端,实现上传文件
- 使用Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- golang简单实现一个基于TLS/SSL的 TCP服务器和客户端
- 【TCP】使用TCP协议写一个可以上传文件的服务器和客户端。
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- 用 TCP 协议写一个客户端和一个服务端,实现上传文件
- 用Reactor框架实现一个简单的tcp服务器
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- 某实例+修改 Winsock实现基于TCP的客户端/服务器通信
- 网络编程资料总结(二)----Tcp多线程服务器和客户端的实现
- 文件下载服务器与客户端实现
- 修改例子,TCP服务器和客户端,加入线程的概念,实现单方多次发送信息
- java socket实现的客户端和服务器端,服务器采用多线程实现,为每个客户分配一个线程
- [译文]Winsock API实现了一个Tcp服务器 - for 初学者
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- 实现客户端与终端服务器间文件轻松互传
- java 通过 socket 实现 服务器和客户端的通信 TCP