1.network.h
#include <iostream>
#include <winsock2.h>
#include <cstring>
class NetWork
{
int type; // 通信协议类型
int sock_fd; // socket 描述符
sockaddr_in addr; // 通信地址
int addrlen; // 通信地址字节数
bool issvr; // 是否是服务器
// 关闭 socket 套接字并释放内存
public:
NetWork(void);
NetWork(int type, const char* ip, short port, bool issvr=false);
~NetWork(void);
bool open(void);
// 等待连接,只有TCP协议的服务器才能调用
NetWork* accept_nw(void);
// 具备 send 和 sendto 的功能
int send_nw(const char*buf,int flag = 0);
int send_nw(const void* buf, size_t len,int flag = 0);
// 具备 recv 和 recvfrom 的功能
int recv_nw(void* buf, size_t len,int flag = 0);
};
2.network.cpp
#include "network.h"
#include <iostream>
#include <stdexcept>
NetWork::NetWork(void)
{
addrlen = sizeof(addr);
type = SOCK_STREAM;
issvr = false;
}
NetWork::NetWork(int type, const char* ip,short port, bool issvr):type(type),issvr(issvr)
{
//不在构造函数中创建socket,因为socket创建可能失败,而构造函数是没有返回值的,不能在此创建
// 初始化地址结构体
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
addrlen = sizeof(addr);
}
NetWork::~NetWork(void)
{
closesocket(sock_fd);
}
bool NetWork::open(void)
{
//创建socket对象
sock_fd = socket(AF_INET,type,0);
if(sock_fd < 0)
{
perror("socket");
return false;
}
//根据type和issvr执行以下流程
if (issvr)
{
// 服务器端绑定和监听
if (bind(sock_fd, (sockaddr*)&addr, addrlen))
{
perror("bind");
return false;
}
if (type == SOCK_STREAM && listen(sock_fd, 50))
{
perror("listen");
return false;
}
}
else if (type == SOCK_STREAM && connect(sock_fd,(sockaddr*)&addr,addrlen))
{
perror("connect");
return false;
}
return true;
}
NetWork* NetWork::accept_nw()
{
if (type != SOCK_STREAM || !issvr)
{
puts("只有type为SOCK_STREAM 且为服务端才能调用该函数\n");
}
NetWork* nw = new NetWork;
nw->sock_fd = accept(sock_fd, (sockaddr*)&nw->addr, &nw->addrlen);
if (nw->sock_fd < 0)
{
delete nw;
perror("accept");
return NULL;
}
return nw;
}
int NetWork::send_nw(const char* buf,int flag )
{
if(type == SOCK_STREAM)
return ::send(sock_fd,buf,strlen(buf)+1,flag);
else
return sendto(sock_fd,buf,strlen(buf)+1,flag,(sockaddr*)&addr,addrlen);
}
int NetWork::send_nw(const void* buf, size_t len,int flag )
{
if (type == SOCK_DGRAM)
{
return sendto(sock_fd, (char*)buf, len, flag, (sockaddr*)&addr, addrlen);
}
else
{
return send(sock_fd,(char*)buf, len, flag);
}
}
int NetWork::recv_nw(void* buf, size_t len,int flag )
{
if (type == SOCK_DGRAM)
{
return recvfrom(sock_fd, (char*)buf, len, flag, (sockaddr*)&addr, &addrlen);
}
else
{
return recv(sock_fd, (char*)buf, len, flag);
}
}
NetWork已经封装好了下面来使用
server.cpp
#include "network.h"
#include <Windows.h>
#include <pthread.h>
#include <cstdlib>
#include <cstring>
using namespace std;
#define buf_size (4096)
void* server(void* arg)
{
NetWork* cnw = static_cast<NetWork*>(arg);
char* buf = new char[buf_size];
for (;;)
{
//接收请求
int ret = cnw->recv_nw(buf, buf_size);
if (ret <= 0 || 0 == strcmp("quit", buf))
{
printf("客户端%d退出\n", cnw);
delete cnw;
delete buf;
return NULL;
}
printf(" recv:%s bits:%d\n", buf, ret);
//响应请求
strcat(buf, "::return");
ret = cnw->send_nw(buf);
if (ret <= 0)
{
printf("客户端退出\n");
delete cnw;
delete buf;
return NULL;
}
}
//关闭
pthread_exit(NULL);
}
int main(int argc,const char * argv[])
{
if(argc!=3)
{
printf("参数格式输入错误:./server + ip + port\n");
return 0;
}
NetWork * snw = new NetWork(SOCK_STREAM,argv[1],atoi(argv[2]),true);
if(!snw->open())
{
delete snw;
return -1;
}
for(;;)
{
NetWork * cnw = snw->accept_nw();
if(cnw ==NULL)
{
continue;
}
pthread_t tid;
pthread_create(&tid, NULL, server, (void*)cnw);
// 分离线程,让线程结束后自动回收资源
pthread_detach(tid);
}
}
client.cpp:不要需要开多线程,服务器开多线程因为,服务器要处理多用户发来的请求
#include "network.h"
#include <Windows.h>
#include <pthread.h>
#include <cstdlib>
#include <cstring>
using namespace std;
#define buf_size (4096)
int main(int argc,const char * argv[])
{
if(argc!=3)
{
printf("参数格式输入错误:./server + ip + port\n");
return 0;
}
NetWork * cnw = new NetWork(SOCK_STREAM,argv[1],atoi(argv[2]));
if(!cnw->open())
{
delete cnw;
return -1;
}
char* buf = new char[buf_size];
for (;;)
{
cout<< "<<<"<<endl;
cin.getline(buf, buf_size);
//发送请求
int ret = cnw->send_nw(buf);
if (ret <= 0)
{
printf("客户端退出\n");
delete cnw;
delete buf;
return 0;
}
//接收请求
ret = cnw->recv_nw(buf, buf_size);
if (ret <= 0 || 0 == strcmp("quit", buf))
{
printf("客户端%d退出\n", cnw);
delete cnw;
delete buf;
return 0;
}
printf(" recv:%s bits:%d\n", buf, ret);
}
//关闭
}