一.C++封装TcpSocket类
#include <iostream>
#include <string>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <cstdio>
#include <unistd.h>
#include <cstdlib>
#include <arpa/inet.h>
using namespace std;
class TcpSocket{
public:
TcpSocket()
:_sockfd(-1)
{}
bool Socket(){
_sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(_sockfd < 0){
perror("socket error");
return false;
}
return true;
}
int GetFd(){
return _sockfd;
}
void SetFd(int fd){
_sockfd = fd;
}
void SetNoBlock(){
int flag = fcntl(_sockfd,F_GETFL,0);
fcntl(_sockfd,F_SETFL,flag|O_NONBLOCK);
}
bool Bind(const string& ip,const int& port){
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = bind(_sockfd,(struct sockaddr*)&addr,len);
if(ret < 0){
perror("bind error");
return false;
}
return true;
}
bool Listen(int backlog = 5){
int ret = listen(_sockfd,backlog);
if(ret < 0){
perror("listen error");
return false;
}
return true;
}
bool Connect(const string& ip,const int& port){
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = connect(_sockfd,(struct sockaddr*)&addr,len);
if(ret < 0){
perror("connect error");
return false;
}
return true;
}
bool Accept(TcpSocket* sock,string* ip = NULL,int* port = NULL){
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
int fd = accept(_sockfd,(struct sockaddr*)&addr,&len);
if(fd < 0){
perror("accept error");
return false;
}
sock->_sockfd = fd;
if(ip != NULL){
*ip = inet_ntoa(addr.sin_addr);
}
if(port != NULL){
*port = ntohs(addr.sin_port);
}
return true;
}
bool Recv(string* buf){
char tmp[4096]={0};
int ret = recv(_sockfd,tmp,4096,0);
if(ret < 0){
perror("recv error");
return false;
}else if(ret ==0){
printf("connect shutdown");
return false;
}
buf->assign(tmp,ret);
return true;
}
bool Send(const string& data){
int total_len = 0; //实际发送的数据长度
while(total_len < data.size()){
int ret = send(_sockfd,data.c_str()+total_len,data.size()-total_len,0);
if(ret < 0){
perror("send error");
return false;
}
total_len+=ret;
}
return true;
}
bool Close(){
if(_sockfd > 0){
close(_sockfd);
_sockfd = -1;
}
}
private:
int _sockfd;
};
二.服务端
#include <iostream>
#include "tcpsocket.hpp"
#define CHECK_RET(q) if(q==false){return -1;}
int main(int argc,char* argv[]){
TcpSocket lis_sock;
string ip = argv[1];
int port = atoi(argv[2]);
//创建套接字
CHECK_RET(lis_sock.Socket());
//绑定地址信息
CHECK_RET(lis_sock.Bind(ip,port));
//监听
CHECK_RET(lis_sock.Listen());
while(1){
TcpSocket srv_sock;
string cli_ip;
int cli_port;
//获取新连接套接字
bool ret = lis_sock.Accept(&srv_sock,&cli_ip,&cli_port);
if(ret == false){
continue;
}
//收发数据
string buf;
ret = srv_sock.Recv(&buf);
if(ret == false){
srv_sock.Close();
continue;
}
printf("client[ %s : %d ] say %s:\n",cli_ip.c_str(),cli_port,buf.c_str());
buf.clear();
cin >> buf;
ret = srv_sock.Send(buf);
if(ret == false){
srv_sock.Close();
}
}
//关闭套接字连接
CHECK_RET(lis_sock.Close());
return 0;
}
三.服务端
#include "tcpsocket.hpp"
#define CHECK_RET(q) if(q==false){return false;}
int main(){
TcpSocket cli_sock;
//创建套接字
CHECK_RET(cli_sock.Socket());
//建立连接请求
CHECK_RET(cli_sock.Connect("192.168.72.128",8000));
//进行收发数据
while(1){
string data;
cin >> data;
CHECK_RET(cli_sock.Send(data));
data.clear();
CHECK_RET(cli_sock.Recv(&data));
printf("server say:%s",data.c_str());
}
//关闭连接
CHECK_RET(cli_sock.Close());
return 0;
}