Server:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>//sleep();
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include<dirent.h>
#include <fcntl.h>
#define SERVER_NET_PORT 4396
#define TRANSPORT_PORT 8888
int initSocket(struct sockaddr_in * in,int sizeOfIn,int port){
int sock;
if ((sock = socket(AF_INET,SOCK_STREAM,0)) == -1) {
printf("创建原始套接字出错!\n");
exit(1);//异常退出1/-1,正常退出0
}
//封装地址:(为本机地址)
in->sin_addr.s_addr = inet_addr("0.0.0.0");
in->sin_family = AF_INET;
in->sin_port = htons(port);
//bind连接socket与ip:
if (bind(sock, (struct sockaddr *)in, sizeOfIn) != 0) {
printf("bind error!\n");
exit(1);
}
return sock;
}
void server_ls(int sock,char * recExCmd){
char sendBuf[1024];
DIR * d = opendir(recExCmd);
struct dirent * e;
while ((e=readdir(d))) {
if (e->d_name[0]!='.') {
// printf("write %s\n",e->d_name);
char a[5] = "\n";
// write(sock, sendBuf, sizeof(sendBuf));
// strcat(e->d_name, a);
strcat(sendBuf, e->d_name);
strncat(sendBuf, a, 1);
}
}
if (write(sock, sendBuf, sizeof(sendBuf)) < 0) {
printf("write error!\n");
}else
printf("write %s",sendBuf);
}
void serverDownload(int sock,char * recExCmd){
int openfd;
char readBuf[1024];
if ((openfd=open(recExCmd, O_RDONLY)) == -1) {
printf("open error!\n");
close(openfd);
}else{//opened!
ssize_t readLen;
//这里用循环是因为可能缓冲区不够容纳整个文件:
while ((readLen=read(openfd, readBuf, sizeof(readBuf))) > 0) {
if (write(sock, readBuf, readLen)<0) {
printf("Open file error!");
break;
}
//将缓冲区清空:
memset(readBuf, 0, sizeof(readBuf));
}
close(openfd);
}
close(sock);
}
int createSockFunc(int acceptfd,int port){
//创建套接字:
int transportAccept;
int transportSock;
struct sockaddr_in transportIn;
struct sockaddr_in recAddr;
socklen_t recAddrLen = sizeof(recAddr);
transportSock = initSocket(&transportIn, sizeof(transportIn),port);
//监听:
if (listen(transportSock, 5) != 0) {
printf("listen error!\n");
exit(1);
}
printf("Established port=%d!\n",port);
//将transportSock的端口信息发送给客户端:
char portInchar[10];
sprintf(portInchar, "%d",port);
if (write(acceptfd, portInchar, sizeof(portInchar)) < 0) {
printf("send port error!\n");
}
printf("port sent!\n");
while ((transportAccept = accept(transportSock,(struct sockaddr*)&recAddr, &recAddrLen)) != -1) {
printf("Accept from : %s\n",inet_ntoa(recAddr.sin_addr));
break;
}
return transportAccept;
}
int main(int argc, const char * argv[]) {
//Server Septs:
/*
1.创建socket
2.循环监听
*/
//创建流套接字:
char recBuf[1024];//
struct sockaddr_in receiveAddr;//
int accceptFd;//
socklen_t receiveAddrLen = sizeof(receiveAddr);
struct sockaddr_in in;
int sock;
//创建套接字:
sock = initSocket(&in,sizeof(in),SERVER_NET_PORT);
//监听:
if (listen(sock, 5) != 0) {
printf("listen error!\n");
exit(1);
}
printf("Established port=%d!\n",SERVER_NET_PORT);
while ((accceptFd = accept(sock, (struct sockaddr *)&receiveAddr, &receiveAddrLen)) != -1) {
printf("来自 %s 的连接!\n",inet_ntoa(receiveAddr.sin_addr));
//连接成功处理信息:(无线程版本)
ssize_t len;
if ((len=read(accceptFd, recBuf, sizeof(recBuf))) < 0) {
printf("read error!\n");
}
printf("recBuf is %s ,len is %ld\n",recBuf,len);
if (0 == strncmp(recBuf, "server_ls", 9)) {
printf("****ls_server****\n");
server_ls(accceptFd,recBuf+10);
printf("****Finished****\n");
}else if (0 == strncmp(recBuf, "download", 8)) {
printf("****download****\n");
int transSock;
transSock = createSockFunc(accceptFd,TRANSPORT_PORT);
serverDownload(transSock,recBuf+9);
printf("****Finished****\n");
}else if (0 == strncmp(recBuf, "upload", 6)){
}else{
printf("cmd wrong!\n");
}
}
return 0;
}
Client:
.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>//close();
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#define SERVER_NET_ADDR "45.77.207.215"
#define SERVER_NET_PORT 4396
#define INPUT_SIZE 50
//不能用这个返回的原因是:char dest是一个局部变量,in stack,执行完就会释放空间,所以返回值永远是NULL
//char * analyse(char * input){
// char dest[50];
// char * p;
// int sizeOfInput = sizeof(input)-2;
// strncpy(dest, input+3,sizeOfInput);//深复制
// p=dest;
//// printf("%p \n %p \n",p,input+3);
// return p;
//}
int initSock(struct sockaddr_in *addr,int port){
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("创建原始套接字出错!\n");
exit(1);//异常退出1/-1,正常退出0
}
//这两种方式都可以将char*类型的地址转换成网络字节序:
addr->sin_addr.s_addr = inet_addr(SERVER_NET_ADDR);
// inet_pton(AF_INET, SERVER_NET_ADDR, &addr.sin_addr);
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
return sockfd;
}
void showServer(char * input,int sockfd){
ssize_t readLen;
char getResponce[1024];
if (write(sockfd, input, INPUT_SIZE) < 0) {
printf("write error!\n");
exit(1);
}
printf("Files are:\n");
if ((readLen=read(sockfd, getResponce, sizeof(getResponce))) < 0) {
printf("server_ls responce error!\n");
exit(1);
}
// printf("readlen=%ld\n",readLen);
printf("%s",getResponce);//自带"\n"
}
void recFile(int sock,char * input){
int openFd;
char readBuf[1024];
char path[100] = "/Users/ron/Desktop/servers.rtf";
if ((openFd=open(path, O_WRONLY|O_CREAT,0666)) == -1) {
printf("open error!\n");
}else{//opened!
ssize_t readLen;
while ((readLen=read(sock, readBuf, sizeof(readBuf))) >0) {
if (write(openFd, readBuf, readLen) <0) {
printf("write error!\n");
close(openFd);
}
}
close(openFd);
}
close(sock);
}
void download(char * input,int sockfd){
struct sockaddr_in in;
int sock;
ssize_t readLen;
//
char recPort[10];
if (write(sockfd, input, INPUT_SIZE) < 0) {
printf("write error!\n");
exit(1);
}
//等待服务器回应(主要是等待服务器开辟的端口信息):
if ((readLen = read(sockfd, recPort, sizeof(recPort))) <0) {
printf("read server port error!\n");
}else{
printf("read size: %ld,and port: %s\n",readLen,recPort);
//初始化客户端套接字:
sock = initSock(&in, atoi(recPort));
while (connect(sock, (struct sockaddr *)&in, sizeof(in)) != 0) {
perror("Connect error!\n");
close(sock);
}
printf("Connect!\n");
//接收文件:
recFile(sock,input);
}
}
void checkCommand(char * input,int sockfd){
if(NULL == input)
{
printf("checkCommand error!\n");
exit(1);
}
else
{
if(0 == strncmp(input, "ls",2)) {
//列出本地文件列表指令
printf("****ls****\n");
DIR * dir = opendir(input+3);//
struct dirent *ep;
while((ep =readdir(dir)))
{
if(ep->d_name[0] != '.')
{
printf("%s\n",ep->d_name);
}
}
printf("**********\n");
}else if(0 == strncmp(input, "server_ls", 9)){
printf("****ls_server****\n");
showServer(input,sockfd);
printf("**********\n");
}else if(0 == strncmp(input, "quit",4)){
//断开链接指令
// close(sockfd);
// exit(0);//正常退出
printf("Quit!\n");
}else if(0 == strncmp(input, "download_", 9)){
//从服务器下载文件指令
printf("****download****\n");
download(input,sockfd);
printf("********\n");
}else{
printf("command wrong!\n");
}
}
}
int main(int argc, const char * argv[]) {
/*Step:
1.创建socket
2.connect
*/
int sockfd;
struct sockaddr_in addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("创建原始套接字出错!\n");
exit(1);//异常退出1/-1,正常退出0
}
//这两种方式都可以将char*类型的地址转换成网络字节序:
addr.sin_addr.s_addr = inet_addr(SERVER_NET_ADDR);
// inet_pton(AF_INET, SERVER_NET_ADDR, &addr.sin_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(SERVER_NET_PORT);
if ((connect(sockfd, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
perror("Connect error!\n");
close(sockfd);
exit(-1);
}
//连接成功!:
printf("Connected to server!\n");
printf("*********Operation Help*********\n"); //操作帮助
printf("显示本地xxx路径文件列表: ls_xxx\n");
printf("显示服务器xxx路径文件列表: server_ls_xxx\n");
printf("实现xxx文件读取与上传: upload_xxx\n");
printf("实现xxx文件下载与存储: download_xxx\n");
printf("断开socket链接: quit\n");
printf("********************************\n");
printf("Please input:\n");
char input[INPUT_SIZE];
scanf("%s",input);//这种输入方式不能有空格
checkCommand(input,sockfd);
close(sockfd);
return 0;
}