前言
前阵子我下载了基于tcp协议的客户端和服务器的代码,想借用一下来处理我们公司软件的日志模块,现在模块没问题了,但是我又想,服务器一般都在linux下,所以又在linux环境下写了一个服务器,也优化了客户端. 期间遇到了一些问题,都记录在这里. 如果哪里有问题,请大家指出,共同进步!
软件名称: 文件服务器
软件功能: 用于局域网内的文件传输
技术涉及:socket网络编程,tcp协议,文件操作,c/c++
软件不足:单线程,局域网,封装度低,数据结构不够精简
未来拓展:多线程,文件夹传输,提高接口封装性,数据结构优化
服务器代码
本来想用纯c写,但是消息体Message用的是类,所以加了头文件<iostream>,后面的话,打算把所有的结构全部封装进对象管理类里,让程序可读性更高,也更精简.
服务器端只完成了接受客户端上传文件,还未支持从服务器端下载文件的功能,大家可以手动添加一下
fileserver.cpp
//fileserver.cpp
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "message.h"
#define SERVERIP "这里写你服务器端的主机IP"
#define PORT 10001
#define MAX_FILE_SIZE 256
#define MAX_BUF_SIZE 1024*10
using std::cout;
using std::endl;
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
char gFileName[256];
int gFileLength;
/function declare
void ProcessConnect(int);
bool RecvFile(int,__MsgHead*);
/fucntion define/
bool RecvFile(int client_sock,__MsgHead* Msg){
cout << "=======================================Enter Function:" << __FUNCTION__ << endl;
//Start to receive file data
FILE* pFile = fopen(gFileName,"w");
if(!pFile){
perror("fopen");
return false;
}
char buf[MAX_BUF_SIZE];
unsigned int i = 0;
while(i < gFileLength - 1)
{
int recv_size = recv(client_sock,buf,MAX_BUF_SIZE,0);
if(recv_size < 0){
perror("recv_");
}
fwrite(buf,sizeof(char), recv_size,pFile);
i += recv_size;
memset(buf,0,sizeof(char)*MAX_BUF_SIZE);
}
fclose(pFile);
return true;
}
void ProcessConnect(int new_sock){
cout << "=======================================Enter Function:" << __FUNCTION__ << endl;
//完成一次连接的处理
//需要循环的来处理客户端发送的数据
char buf[MAX_BUF_SIZE];
while(1){
memset(buf,0,sizeof(buf));
//a)从客户端读取数据
int recv_size = recv(new_sock,buf,sizeof(buf),0);
if(recv_size == -1)
{
perror("recv__");
return;
}
if(recv_size == 0){
printf("[client %d] disconnect!\n", new_sock);
}
__MsgHead* msgHead = (__MsgHead*)buf;
//b)根据消息ID 响应客户端消息
switch(msgHead->msgId){
case MSG_FILE:
{
cout << "=======================================MSG_FILE" << endl;
if(!RecvFile(new_sock,(__MsgHead*)buf))
{
printf("receive file falied\n");
return;
}
}break;
case MSG_FILE_NAME:
{
cout << "=======================================MSG_FILE_NAME" << endl;
__MsgFileName* msg;
msg = (__MsgFileName*)msgHead;
strcpy(gFileName,msg->fileName);
printf("The file name that has been received is:%s\n",gFileName);