350、实现文件传输功能
一、demo11.cpp
/*
* 程序名:demo11.cpp,此程序用于演示文件传输的客户端。
*/
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;
class ctcpclient // TCP 通讯的客户端类。
{
private:
int m_clientfd; // 客户端的 socket,-1 表示未连接或连接已断开;>=0 表示有效的
socket。
string m_ip; // 服务端的 IP/域名。
unsigned short m_port; // 通讯端口。
public:
ctcpclient():m_clientfd(-1) {}
// 向服务端发起连接请求,成功返回 true,失败返回 false。
bool connect(const string &in_ip,const unsigned short in_port)
{
if (m_clientfd!=-1) return false; // 如果 socket 已连接,直接返回失败。
m_ip=in_ip; m_port=in_port; // 把服务端的 IP 和端口保存到成员变量中。
// 第 1 步:创建客户端的 socket。
if ( (m_clientfd = socket(AF_INET,SOCK_STREAM,0))==-1) return false;
// 第 2 步:向服务器发起连接请求。
struct sockaddr_in servaddr; // 用于存放协议、端口和 IP 地址的结构体。
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; // ①协议族,固定填 AF_INET。
servaddr.sin_port = htons(m_port); // ②指定服务端的通信端口。
struct hostent* h; // 用于存放服务端 IP 地址(大端序)的结构体的
指针。
if ((h=gethostbyname(m_ip.c_str()))==nullptr ) // 把域名/主机名/字符串格式的 IP转换成结
构体。
{
::close(m_clientfd); m_clientfd=-1; return false;
}
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length); // ③指定服务端的 IP(大端序)。
// 向服务端发起连接清求。
if (::connect(m_clientfd,(struct sockaddr *)&servaddr,sizeof(servaddr))==-1)
{
::close(m_clientfd); m_clientfd=-1; return false;
}
return true;
}
// 向服务端发送报文(字符串),成功返回 true,失败返回 false。
bool send(const string &buffer) // buffer 不要用 const char *
{
if (m_clientfd==-1) return false; // 如果 socket 的状态是未连接,直接返回失败。
if ((::send(m_clientfd,buffer.data(),buffer.size(),0))<=0) return false;
return true;
}
// 向服务端发送报文(二进制数据),成功返回 true,失败返回 false。
bool send(void *buffer,const size_t size)
{
if (m_clientfd==-1) return false; // 如果 socket 的状态是未连接,直接返回失败。
if ((::send(m_clientfd,buffer,size,0))<=0) return false;
return true;
}
// 接收服务端的报文,成功返回 true,失败返回 false。
// buffer-存放接收到的报文的内容,maxlen-本次接收报文的最大长度。
bool recv(string &buffer,const size_t maxlen)
{ // 如果直接操作 string 对象的内存,必须保证:1)不能越界;2)操作后手动设置数据的大小。
buffer.clear(); // 清空容器。
buffer.resize(maxlen); // 设置容器的大小为
03-22
08-12
11-12
490
