本例子是本人Linux下基于TCP多线程Socket编程的第二个例子,本例子是用C++实现的
服务器采用了面向对象的多线程,用到了队列与链表,信号量(操作系统中叫PV操作)
本例子中的队列与链表源代码在前面可以找到,这里就不多贴了
此系统所支持的自定义命令跟上个例子相同,就里就不多说明了
头文件Thread.h代码,里面就一个抽象类(抽象类没有自己的实例,一定要被子类所继承)
#ifndef THREAD_H_INCLUDED
#define THREAD_H_INCLUDED
class Thread
{
public:
void ThreadEnter();
protected:
virtual void Start() = 0;
virtual void Initialize(){}
};
#endif // THREAD_H_INCLUDED
Thread.cpp代码:
#include "Thread.h"
void Thread::ThreadEnter()
{
Start();
}
以下为服务器主要头文件Server.h代码:
#ifndef SERVER_H_INCLUDED
#define SERVER_H_INCLUDED
#include "Thread.h"
#include "LinkList.h"
#include "ThreadQueue.h"
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#define MSG_SIZE 1024
#define BACKLOG 10
#define PORT 8001
class Server : public Thread
{
public:
Server();
~Server();
public:
void Start();
void Initialize();
void SendMessage(Server* serer);
static void* SendMessageThread(void* param);
void ReadMessage(Server* server);
static void* ReadMessageThread(void* param);
private:
int sock_fd,new_fds[BACKLOG],new_fd;
struct sockaddr_in serv_addr,dest_addr;
pthread_mutex_t mutex;
pthread_t pth_r,pth_s;
sem_t sem_r,sem_s;
int thread_cout;
LinkList list;
ThreadQueue queue;
DataType *pData;
};
#endif // SERVER_H_INCLUDED
以下为Thread.h实现的Thread.cpp代码:
#include "Server.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
using namespace std;
//------------------------------------------------------------------
Server::Server()
{
pthread_mutex_init(&mutex,NULL);
sem_init(&sem_r,0,10);
sem_init(&sem_s,0,0);
}
//------------------------------------------------------------------
void Server::Initialize()
{
sock_fd = socket(AF_INET,SOCK_STREAM,0);
if(sock_fd < 0)
{
perror("socket fail!" );
exit(-1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = ntohs(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(serv_addr.sin_zero), 8);
if (bind(sock_fd, (struct sockaddr*) &serv_addr,
sizeof(struct sockaddr)) < 0)
{
perror("bind fail! ");
exit(-1);
}
if(listen(sock_fd,BACKLOG) < 0)
{
perror("listen fail!" );
exit(-1);
}
cout << "listenning......" << endl;
socklen_t sin_size = sizeof(dest_addr);
while(1)
{
if(thread_cout == BACKLOG - 1)
{
return;
}
new_fd = accept(sock_fd,(struct sockaddr *)&dest_addr,&sin_size);
if(new_fd < 0)
{
perror("accept fail!" );
exit(-1);
}
cout << "\nA client has connected to me "
<< inet_ntoa(dest_addr.sin_addr)
<< ":" << ntohs(dest_addr.sin_port)
<< endl;
pthread_mutex_lock(&mutex);
thread_cout++;
list.InsertNode(thread_cout,new_fd);
pthread_mutex_unlock(&mutex);
pthread_create(&pth_r,NULL,ReadMessageThread,this);
}
}
//------------------------------------------------------------------
void Server::Start()
{
pthread_create(&pth_s,NULL,SendMessageThread,this);
Initialize();
}
//------------------------------------------------------------------
void Server::ReadMessage(Server* server)
{
int fd = server->new_fd;
char buf[MSG_SIZE];
int len;
/*
pthread_mutex_lock(&mutex);
int count = thread_cout - 1;
pthread_mutex_unlock(&mutex);
*/
while(1)
{
sem_wait(&sem_r);
if ((len = read(fd, buf, MSG_SIZE)) == -1)
{
perror("read fail!");
pthread_exit(NULL);
}
else if (len == 0)
{
cout << "Current client has disconnected to me" << endl;
//cout << "close fd = " << fd << endl;
close(fd);
list.DeleteNode(fd);
pthread_exit(NULL);
}
//cout << "read fd = " << fd << endl;
buf[len] = '\0';
DataType *data = new DataType();
data->fd = fd;
strcpy(data->buff,buf);
cout << "\nRECEIVE: " << buf
<< " receive fd = " << fd << endl;
//pthread_mutex_lock(&mutex);
queue.EnterQueue(data);
//pthread_mutex_unlock(&mutex);
//delete data;
sem_post(&sem_s);
}
}
//------------------------------------------------------------------
void* Server::ReadMessageThread(void* param)
{
Server* server = (Server *)param;
server->ReadMessage(server);
return NULL;
}
//------------------------------------------------------------------
void Server::SendMessage(Server* server)
{
while(1)
{
sem_wait(&sem_s);
int list_len = list.GetLength();
int tNewfd,tReceivefd;
//pthread_mutex_lock(&mutex);
pData = queue.OutQueue();
//int queue_len = queue.Queuelength();
//pthread_mutex_unlock(&mutex);
tReceivefd = pData->fd;
//cout << "Received fd = " << tReceivefd << endl;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= list_len; i++)
{
list.GetNodeData(i,tNewfd);
//cout << "New fd = " << tNewfd << endl;
//if(queue_len != 0)
//{
if(tNewfd != tReceivefd)
{
write(tNewfd,pData->buff,sizeof(pData->buff));
cout << "Send to client successful! fd = " << tNewfd << endl;;
}
//}
}
delete pData;
pthread_mutex_unlock(&mutex);
sem_post(&sem_r);
}
}
//------------------------------------------------------------------
void* Server::SendMessageThread(void* param)
{
Server* server = (Server *)param;
server->SendMessage(server);
return NULL;
}
//------------------------------------------------------------------
Server::~Server()
{
close(sock_fd);
pthread_join(pth_r,NULL);
pthread_join(pth_s,NULL);
}
//------------------------------------------------------------------
以下为主文件main.cpp代码:
#include "Server.h"
int main(void)
{
Server* server = new Server();
server->ThreadEnter();
return 0;
} <!--v:3.2-->
分享到:
相关推荐
Linux系统下基于Tcp的多线程大文件上传实现.pdf
在Windows下,使用多线程实现基于TCP的Socket通信(C++)。
这是一个基于Linux系统使用C语言编写的关于TCP和线程结合起来的网络聊天室的源码,内附Makefile可直接编译和运行,可以直接认识TCP和线程的基本原理。
C语言编写,采用CS模型,TCP、UDP网络协议实现的内网多人聊天室。 服务器:采用多线程以及线程锁处理客户端的所有请求以及信息转发任务。服务端实时显示客户的登录与登出信息;保存客户上传的共享文件(网盘功能);...
linux c tcp socket 多线程 简单聊天室 ,服务器端负责转发,代码很简陋有待改进
主要功能: (1)私聊 (2)群聊 实现方法:(具体参考代码) (1)服务端:起初使用多进程和管道,但没有实现;后来我就使用了多线程。 客户端:使用多进程,采用I/O分割模型。
该聊天室可以实现公聊和私聊的功能,基于tcp的实现,用到多线程
基于tcp协议的linux下的socket编程。
linux下的字符传输程序,基于TCP协议,使用多线程,可实现服务器与多个客户端的连接与字符传输.
我自己练习用的LINUX的习题问答程序。软件尚有bug,但是90%可用。...主要使用socket、tcp、多进程、多线程、IO以及sqlite3的练习。client.C中需要自己设定配置本机的IP。可以自行扩充数据库,修改代码。
本程序是Linux下基于socket套接字完成的简单网络编程程序,可以接收Tcp、Udp单播、Udp组播消息,并且加入了Select机制和多线程编程,比较简单,适合初学者使用。
liux 下的基于tcp的多线程扫描器; 建立连接,开多个线程同时多目标进行扫描(可同时5个目标),从端口1到65535;
在Linux下c语言实现的基于TCP/IP的ftp文件传输程序,包含完整的源代码,分为客户端程序和服务器端程序
我用MFC VC6编写的一个 TCP 一对多通信的程序,就是服务器端利用多线程技术(不使用Select等任何模型), 能同时接收多个客户端的消息, 其次, 服务器端还能将消息群发给所有已连接的客户端, 实现的基本思路 是将...
Linux下tcp通信程序,含客户端和服务器以及Makefile,多线程-可同时收发操作。 不足:退出机制不太完整。
基于Tcp/IP的Linux文件传输系统,分为服务器和客户端模块,共有账号管理,信息管理,资源管理,上传,下载、查找、浏览等基本功能,且支持断点续传,非常棒的一个功能,且,在传输过程中,用OpenSSL对数据进行加密,...
可实现私信、创建用户名、实况聊天、显示时间
硬件平台为 iTop-4412,此程序是运行在嵌入式linux系统上的TCP/IP 服务端程序,主函数用于建立和客户端的连接,建立完成后,会新增一个线程用于实时数据传输。
分别用UDP、TCP、多线程通信三种方式实现socket编程,是学习socket编程最全的小项目,是linux高级编程学习必须部分,现在我工作基本天天都跟他们打交道
Linux系统是一个免费使用和自由传播的类Unix操作系统,基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统,Linux是许多企业...