收发文件的服务器端/客户端实现
程序员文章站
2022-03-04 22:20:34
...
程序需求
- 客户端接受用户输入的传输文件名
- 客户端请求服务器端传输该文件名所指文件
服务器端代码:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
const int bufSize = 1024;
void error_handling(const std::string &message);
int main(int argc, char *argv[])
{
int serv_sock, clnt_sock;
char buffer[bufSize];
int str_len, i;
struct sockaddr_in serv_addr, clnt_addr;
socklen_t clnt_addr_sz;
if(argc != 2) {
std::cout << "Usage : " << argv[0] << " <port>" << std::endl;
exit(1);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1]));
if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
error_handling("bind() error");
if(listen(serv_sock, 1) == -1)
error_handling("listen() error");
clnt_addr_sz = sizeof(clnt_addr);
for(size_t cnt = 0; true; ++cnt) {
// get client socket
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_sz);
if(clnt_sock == -1)
error_handling("accept() error");
std::cout << "Client connected, seq:" << cnt << std::endl;
// get the filename
memset(buffer, 0, bufSize);
if((recv(clnt_sock, buffer, bufSize, 0)) < 0) {
error_handling("failed to filename data!");
break;
}
// start transmission
std::string filename(buffer);
FILE *fp = fopen(filename.c_str(), "r");
if(fp == NULL)
std::cout << "NO_SUCH_FILE_REQUEST" << std::endl;
else {
memset(buffer, 0, bufSize);
int sd_sz; // size of data to send
while((sd_sz = fread(buffer, 1, bufSize, fp)) > 0) {
if(send(clnt_sock, buffer, sd_sz, 0) < 0) { // see if failed
std::cout << "SEND_FILD_FAILED" << std::endl;
break;
}
memset(buffer, 0, bufSize);
}
fclose(fp);
}
close(clnt_sock);
std::cout << "clnt_sock closed (seq:" << cnt << ")" << std::endl;
}
close(serv_sock);
return 0;
}
void error_handling(const std::string &message) {
std::cerr << message << std::endl;
exit(1);
}
客户端代码:
#include <iostream>
#include <string>
#include <regex>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
const int bufSize = 1024;
void error_handling(const std::string &message);
int filename_check(const std::string &filename);
int main(int argc, char *argv[]) {
int sock;
char buffer[bufSize];
std::string str_msg;
int str_len;
struct sockaddr_in serv_addr;
if(argc != 3) {
std::cout << "usage : " << argv[0] << " <IP> <port>" << std::endl;
exit(1);
}
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("connect() error!");
std::cout << "Connected......" << std::endl;
std::cout << "Use 'quit' to finish the download" << std::endl;
// get filename
std::cout << "Input filename: " << std::ends;
getline(std::cin, str_msg);
// ATTENTION: these check should have been implemented in the server
if(filename_check(str_msg) != 0)
return 0;
// check
FILE *fp = fopen(str_msg.c_str(), "w");
if (fp == NULL)
error_handling("Can't open/create the file!");
if((send(sock, str_msg.c_str(), str_msg.length(), 0)) < 0)
error_handling("Send filename failed");
std::cout << "filename sent..." << std::endl;
int recv_sz;
while( (recv_sz = recv(sock, buffer, bufSize-1, 0)) > 0 ) { // receive the data
if(fwrite(buffer, recv_sz, 1, fp) < 0) { // write to a file
std::cout << "Failed to write the file!" << std::endl;
break;
}
memset(buffer, 0, bufSize);
}
std::cout << "Download finished..." << std::endl;
fclose(fp);
close(sock);
return 0;
}
void error_handling(const std::string &message) {
std::cerr << message << std::endl;
exit(1);
}
int filename_check(const std::string &filename) {
// check quit
if(std::regex_match(filename, std::regex("[Qq]uit"))) {
std::cout << "Client closed....." << std::endl;
return 1;
}
// check illegal filename
if(std::regex_match(filename, std::regex(".*(([\\.]{2})|([/])).*"))) {
std::cout << "illegal filename!" << std::endl;
return 2;
}
return 0;
}
上一篇: Linux内核网络栈1.2.13-icmp.c概述
下一篇: GBase 8c 全文检索-表检索
推荐阅读
-
php glob实现目录文件遍历与寻找与模式匹配的文件路径
-
用php实现动态产生xml文件以及从xml文件中抽取数据转化成html的小程序_PHP教程
-
php用ZipArchive函数实现文件的压缩与解压缩
-
yii2.0框架实现上传excel文件后导入到数据库的方法示例
-
使用php完成一个用户注册以及管理的demo(php实现单文件与多文件的上传)
-
Python使用tablib生成excel文件的简单实现方法
-
qq邮箱中转站zip rar压缩文件预览用php是如何实现的
-
php清空(删除)指定目录下的文件,不删除目录文件夹的实现代码_PHP
-
php使用pclzip类实现文件压缩的方法(附pclzip类下载地址),
-
用PHP文件上传的具体思路及实现_PHP教程