前言
该篇博文是上一篇文章 Linux 网络编程笔记 [1] —— 套接字 Socket 实现最简版 FTP 服务(C语言)里FTP服务的第二种实现。在源代码框架大致相同的情况下,些许细节微微不同或许还有一点点粗糙,对此笔者也不再继续做优化了。另外,在此特别感谢「哞哞教育」江兴畿讲师的辛苦讲解。
服务端代码 service.c
/* service.c */
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include<netinet/in.h>
#include <unistd.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
int change(char *cmd);
char *getbehind(char *cmd);
void getmessage(char cmd[128], int cfd);
void chooseCmd(char cmd[128], int c_fd);
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int s_read;
char Writebuf[128];
char Readbuf[128];
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
perror("argc");
exit(-1);
}
//1.socket
s_fd = socket(AF_INET, SOCK_STREAM, 0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
memset(&s_addr, 0, sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &s_addr.sin_addr);
//2.bind
bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
//3.listen
listen(s_fd, 10);
printf("等待客户端的连接……\n");
memset(&c_addr, 0, sizeof(struct sockaddr_in));
int clen = sizeof(struct sockaddr_in);
while(1){
//4.accept
c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &clen);
if(c_fd == -1){
perror("accept");
exit(-1);
}
printf("与客户端取得连接:%s.\n",inet_ntoa(c_addr.sin_addr));
//5.read & write cycle.
if(fork() == 0){
while(1){
memset(Readbuf, 0, sizeof(Readbuf));
//服务端处于被动状态,等待来自客户端的指令。
s_read = read(c_fd, Readbuf, 128);
if(s_read == 0){
printf("The client exits directly!\n");
break;
}else if(s_read > 0){
chooseCmd(Readbuf,c_fd);
memset(Readbuf,0,sizeof(Readbuf));
}
}
}
}
close(c_fd);
close(s_fd);
return 0;
}
void chooseCmd(char cmd[128],int c_fd)
{
int sfd;
FILE *fdb;
char *readbuf = (char*)malloc(128);
char freadbuf[128];
char *p = (char *)malloc(8000);
int ret = change(cmd);
switch(ret){
case 1:
//函数popen与函数open的差异?
fdb = popen("ls", "r");
fread(freadbuf, sizeof(freadbuf), 1, fdb);
write(c_fd, freadbuf, sizeof(freadbuf));
memset(freadbuf, 0, sizeof(freadbuf));
printf("ls ok.\n");
break;
case 2:
//了解ps命令。
system("ps");
printf("ps ok.\n");
break;
case 3:
p = getbehind(cmd);
chdir(p);
memset(p, 0, sizeof(p));
break;
case 4:
read(c_fd, freadbuf, sizeof(freadbuf));
printf("%s\n",freadbuf);
exit(1);
break;
case 5://get
readbuf = getbehind(cmd);
if(access(readbuf, F_OK) == -1){
write(c_fd, "NO file", strlen("NO file"));
}else{
sfd = open(readbuf, O_RDWR, 0666);
read(sfd, p, 8000);
write(c_fd, p, strlen(p));
close(sfd);
memset(p, 0, 8000);
}
break;
case 6: //put
getmessage(cmd, c_fd);
break;
}
}
int change(char *cmd)
{
if(!strcmp("ls",cmd)) {return 1;}
else if(!strcmp("ps",cmd)) {return 2;}
else if(strstr(cmd,"cd")!=NULL) {return 3;}
else if(!strcmp("g",cmd)) {return 4;}
else if(strstr(cmd,"get")!=NULL) {return 5;}
else if(strstr(cmd,"put")!=NULL) {return 6;}
}
char *getbehind(char *cmd)
{
char *p;
p = strtok(cmd, " ");
p = strtok(NULL, " ");
return p;
}
void getmessage(char cmd[128],int cfd)
{
char readbuf[8000];
char *p = getbehind(cmd);
read(cfd, readbuf, 8000);
int fd = open(p, O_RDWR|O_CREAT, 0666);
write(fd, readbuf, strlen(readbuf));
printf("receive successfully\n");
close(fd);
memset(readbuf,0,8000);
}
客户端代码 client.c
/* client.c */
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include<netinet/in.h>
#include<stdlib.h>
#include <unistd.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
int change(char cmd[128]);
char *getbehind(char cmd[128]);
void getmessage(char *cmd,int cfd);
void putmessage(char cmd[128],int c_fd);
void chooseCmd(char *cmd, int c_fd);
int main(int argc,char **argv)
{
int c_fd;
int nread;
char Readbuf[1024];
char Writebuf[128];
char buf[256];
struct sockaddr_in c_addr;
if(argc != 3){
perror("argc error");
exit(-1);
}
c_fd = socket(AF_INET, SOCK_STREAM, 0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
int clent = sizeof(struct sockaddr_in);
if( (connect(c_fd,(struct sockaddr *)&c_addr,clent)) == -1){
perror("connect");
exit(-1);
}
printf("与服务端建立连接中……\n");
while(1){
gets(Writebuf);
printf("Client's cmd:%s\n",Writebuf);
write(c_fd,Writebuf,strlen(Writebuf));
chooseCmd(Writebuf,c_fd);
printf("***************Cmd Send Over.***************\n");
memset(Writebuf,0,strlen(Writebuf));
}
return 0;
}
int change(char cmd[128])
{
if(!strcmp("lls",cmd)) {return 1;}
else if(strstr(cmd,"lcd")!=NULL) {return 2;}
else if(!strcmp("g",cmd)) {return 3;}
else if(!strcmp("ls",cmd)) {return 4;}
else if(strstr(cmd,"cd")!=NULL) {return 5;}
else if(strstr(cmd,"get")!=NULL) {return 6;}
else if(strstr(cmd,"put")!=NULL) {return 7;}
}
char *getbehind(char cmd[128])
{
char *p;
p = strtok(cmd, " ");
p = strtok(NULL, " ");
return p;
}
void chooseCmd(char *cmd, int c_fd)
{
FILE *fdb;
int ret = change(cmd);
char freadbuf[128];
char *p = (char *)malloc(8001);
switch(ret){
case 1:
system("ls"); //lls
break;
case 2:
p = getbehind(cmd); //lcd
chdir(p);
memset(p,0,8000);
break;
case 3:
printf("unconnecting\n"); //g
write(c_fd,"away host",128);
close(c_fd);
exit(-1);
break;
case 4:
read(c_fd,p,1024); //ls
printf("%s\n",p);
memset(p,0,1024);
break;
case 5:
printf("host folder open or exit successful\n"); //cd
break;
case 6:
getmessage(cmd,c_fd); //get
break;
case 7:
putmessage(cmd,c_fd); //put
break;
default:
printf("Cmd error!\n");
break;
}
}
void getmessage(char *cmd,int cfd)
{
int fd;
char readbuf[8000];
char *p = getbehind(cmd);
read(cfd, readbuf, 8000);
if(strlen(readbuf) != strlen("NO file")){
fd = open(p,O_RDWR|O_CREAT,0666);
write(fd,readbuf,strlen(readbuf));
printf("receive successfully\n");
close(fd);
memset(readbuf,0,8000);
}else{
printf("NO this file!\n");
}
}
void putmessage(char cmd[128],int c_fd)
{
int sfd;
char *p = (char *)malloc(8000);
memset(p, 0, 8000);
char *readbuf = (char *)malloc(128);
readbuf = getbehind(cmd);
if(access(readbuf, F_OK) == -1){
printf("No file.\n");
}else{
sfd = open(readbuf,O_RDWR,0666);
read(sfd,p,8000);
write(c_fd,p,strlen(p));
close(sfd);
memset(p, 0, 8000);
}
}
文章更新记录
- 文章完成。「2022.7.1 22:27」