//内容描述:服务器通过socket接收数据,他不停地监听是否有客户端来与其进行连接,如果有,就建立一个线程来处理客户端发过来的数据,如果客户端发送数据结束或者由于某种原因服务器端接收数据失败,则服务器终止接收。
//在这里简单地实现一下,如果在工作当中要用到这种传输模型,则要比这个要考虑的严谨的多。如更健全的数据封装,异常处理,数据池,发送失败处理,接收失败处理,数据保存,甚至是还要加上生产者消费者模型。
//客户端程序很简单
// more Client.cpp
#include <iostream>
using namespace std;
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstdlib>
int main()
{
int sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1)cout << "client socket create error" << endl,exit(-1);
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(22222);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
if(res == -1)cout << "connect failed" << endl,exit(-2);
cout << "start send messages" << endl;
char buf[222] = {};
cin.getline(buf,222);
//发送数据,为了让服务端能更容易看出多线程的效果,这里让同一条信息连续发送15次,
//每次隔一秒,这样就有可能一个人,用同一台机子,启动多个客户端,以便可以观察到服务器的动态,哎,这样处理也是用心良苦啊~~
int i =15;
while(i--)
{
send(sd, buf, sizeof(buf), 0);
sleep(1);
}
close(sd);
return 0;
}
//服务器端
#include <iostream>
using namespace std;
#include <cstdlib>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstring>
#include "thread_base.h"
class RecvData:public ThreadBaseClass
{
public:
int csd;
char buf[222];
public:
RecvData()
{
csd = -1;
memset(buf, 0, sizeof(buf));
}
public:
void run()
{
int res;
while(1)
{
res = recv(csd, buf, sizeof(buf), 0);
if(res > 0)
cout << buf << endl;
else
{
close(csd);
break;
}
}
cout << "delete this" << endl;
delete this;//注意垃圾回收,虽然“delete this ”这种方式很不雅观,但是它也可以达到及时回收内存的效果。
}
};
int main()
{
int sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1)cout << "socket create error" << endl,exit(-1);
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(22222);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = bind(sd, (struct sockaddr*)&addr, sizeof(addr));
if(res == -1)cout << "bind error" << endl,exit(-2);
cout << "bind success" << endl;
if(-1 == listen(sd,10))cout << "listen error" << endl,exit(-3);
struct sockaddr_in c_addr = {};
socklen_t len = sizeof c_addr;
while(1)
{
cout << "start accept" << endl;
int csd = accept(sd, (struct sockaddr*)&c_addr, &len);
cout << "accept success" << endl;
RecvData *pRecvData = new RecvData();
pRecvData->csd = csd;
pRecvData->start();
}
return 0;
}