//tcpserver.h
#ifndef TCPSOCKETSERVER_H
#define TCPSOCKETSERVER_H
#include
#include
#include
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#include /* superset of previous */
#include
/*in_addr_t inet_addr(const char *cp);*/
/*uint16_t htons(uint16_t hostshort);*/
/*int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);*/
/*ssize_t recv(int sockfd, void *buf, size_t len, int flags);*/
class CTcpSocket{
public:
CTcpSocket(int port);
~CTcpSocket();
int createSocket(); /*创建套接字*/
int getAccpet(); /*接收客户端请求并创建一个用于通信的套接字*/
std::string socketRecv(int clientSocketfd); /*接收数据*/
bool socketSend(int clientSocketfd,std::string strSend); /*发送数据*/
void closeCliSocket(int clientfd);
void closeScvSocket();
private:
int m_nPort;
int m_nServerfd;
struct sockaddr_in m_sock_addr,m_client_addr;
socklen_t m_addrlen;
char *m_pRcvbuf;
char *m_pSendbuf;
};
#endif
//tcpserver.cpp
#include "tcpserver.h"
#define BUF_SIZE 1024
CTcpSocket::CTcpSocket(int port)
{
m_nPort = port;
m_pSendbuf = new char[BUF_SIZE];
if(!m_pSendbuf)
{
fprintf(stderr,"mem alloc failure!\n");
}
m_pRcvbuf = new char[BUF_SIZE];
if(!m_pRcvbuf)
{
fprintf(stderr,"mem alloc failure!\n");
}
}
CTcpSocket::~CTcpSocket()
{
if (m_pSendbuf)
{
delete[] m_pSendbuf;
m_pSendbuf = NULL;
}
if (m_pRcvbuf)
{
delete[] m_pRcvbuf;
m_pRcvbuf = NULL;
}
}
int CTcpSocket::createSocket()
{
//step 1 create socket
m_nServerfd = socket(AF_INET, SOCK_STREAM, 0);
if (m_nServerfd < 0)
{
perror("socket()");
return -1;
}
int nZero = 1;
int ret = setsockopt(m_nServerfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&nZero, sizeof(int));
if (ret < 0)
{
perror("setsocket()");
return -2;
}
//step 2 bind socket
m_sock_addr.sin_family = AF_INET;
m_sock_addr.sin_port = htons(m_nPort);
//sock_addr.sin_addr.s_addr = inet_addr("192.168.155.6");
m_sock_addr.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY
ret = bind(m_nServerfd, (struct sockaddr *)&m_sock_addr, sizeof(m_sock_addr));
if (ret < 0)
{
perror("bind()");
return -3;
}
//step 3 start listen
ret = listen(m_nServerfd, 5); //Up to 11 device connections are allowed
if (ret < 0)
{
perror("listen()");
return -4;
}
return m_nServerfd;
}
int CTcpSocket::getAccpet()
{
//step 4 receive client request and create a new socket
int nRetClientfd = accept(m_nServerfd, (struct sockaddr *)&m_client_addr, &m_addrlen);
if (nRetClientfd < 0)
{
perror("accept()");
return -1;
}
return nRetClientfd;
}
std::string CTcpSocket::socketRecv(int clientSocketfd)
{
//step 4 read data buf
memset(m_pRcvbuf, 0, BUF_SIZE);
int ret = recv(clientSocketfd, m_pRcvbuf, BUF_SIZE, 0);
if (ret < 0)
{
perror("recv()");
return "recv error";
}
if (ret == 0)
{
close(clientSocketfd);
return "client exit";
}
std::string retstr = std::string(m_pRcvbuf, ret);
return retstr;
}
bool CTcpSocket::socketSend(int clientSocketfd,std::string strSend)
{
memset(m_pSendbuf, '\0', BUF_SIZE);
strcpy(m_pSendbuf, strSend.c_str());
int ret = send(clientSocketfd, m_pSendbuf, BUF_SIZE, 0);
if (ret < 0)
{
perror("send()");
return false;
}
return true;
}
void CTcpSocket::closeScvSocket()
{
close(m_nServerfd);
}
void CTcpSocket::closeCliSocket(int clientfd)
{
close(clientfd);
}
#include "tcpserver.h"
#include
#include
#include
//makefile文件
CC = g++
MV = mv
CP = cp
RM = rm
LIBTHREAD = -lpthread
CFLAGS = -g
BIN = ../bin
all: $(BIN)/server
$(BIN)/server:tcpserver.o main.o
$(CC) -o $@ $^ $(LIBTHREAD)
.SUFFIXES:.cpp .o
.cpp.o:
$(CC) $(CFLAGS) -c $*.cpp -o $*.o -Wall
.PHONY:clean
clean:
rm -rf *.o $(BIN)/server
#include "chatwidget.h"
#include "ui_chatwidget.h"
ChatWidget::ChatWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ChatWidget)
{
ui->setupUi(this);
ui->textEdit_ALL->setStyleSheet("QTextEdit { background: #cc9966 }");
ui->textEdit_SEND->setStyleSheet("QTextEdit { background: #cccccc }");
ui->textEdit_RECV->setStyleSheet("QTextEdit { background: #cccccc }");
ui->textEdit_SEND->installEventFilter(this);//设置完后自动调用其eventFilter函数
//设置焦点
setFocustoEnd();
tcpsocket = new QTcpSocket(this);
//接收数据
connect(tcpsocket,&QTcpSocket::readyRead,[=]()
{
QString strRecv = tcpsocket->readAll().data();
qDebug() << strRecv;
if(!strRecv.isEmpty())
{
if(strRecv.mid(0,7) == "curroom")
{
//只获取昵称
ui->textEdit_ALL->clear();
QStringList strList = strRecv.mid(7,strRecv.length()).split(" ");
for(int i=0; i").arg(strList[i]).arg("");
ui->textEdit_ALL->append(strMsg);
}
}
else if(strRecv.mid(0,7) == "dispsvr")
{
QString strMsg = QString("%1%2%3").arg("").arg(strRecv.mid(7,strRecv.length())).arg("");
ui->textEdit_RECV->append(strMsg);
}
else
{
QMessageBox::warning(this,"温馨提示","昵称已被使用,请更换");
}
QApplication::alert(this);
}
});
}
ChatWidget::~ChatWidget()
{
delete ui;
delete tcpsocket;
}
//退出
void ChatWidget::on_pushButton_EXIT_clicked()
{
this->close();
}
//清空
void ChatWidget::on_pushButton_CLEAR_clicked()
{
ui->textEdit_SEND->clear();
setFocustoEnd();
}
//发送
void ChatWidget::on_pushButtonSEND_clicked()
{
//获取用户输入的信息
QString strData = "dispsvr";
strData += ui->textEdit_SEND->toPlainText();
if(strData.mid(0,7) == "dispsvr" && strData.length() > 7)
{
tcpsocket->write(strData.toUtf8());
tcpsocket->waitForBytesWritten();
this->tcpsocket->flush();
ui->textEdit_SEND->clear();
setFocustoEnd();
}
}
//回车键发送
bool ChatWidget::eventFilter(QObject *target, QEvent *event)
{
if(target == ui->textEdit_SEND)
{
if(event->type() == QEvent::KeyPress)//回车键
{
QKeyEvent *k = static_cast(event);
if(k->key() == Qt::Key_Return)
{
//获取用户输入的信息
QString strData = "dispsvr";
strData += ui->textEdit_SEND->toPlainText();
//发送消息
tcpsocket->write(strData.toUtf8());
tcpsocket->waitForBytesWritten();
this->tcpsocket->flush();
if(strData.mid(0,7) == "dispsvr" && strData.length() > 7)
{
ui->textEdit_SEND->clear();
setFocustoEnd();
}
return true;
}
}
}
return QWidget::eventFilter(target,event);
}
//登录
void ChatWidget::on_pushButton_login_clicked()
{
//连接到服务器
QString ip = ui->lineEdit_IP->text();
quint16 port = ui->lineEdit_PORT->text().toUShort();
tcpsocket->connectToHost(QHostAddress(ip),port);
//发送房间号+昵称
QString room = "useradd";
room += ui->lineEdit_ROOM->text();
room += " ";
room += ui->lineEdit->text();
tcpsocket->write(room.toUtf8());
setFocustoEnd();
}
void ChatWidget::setFocustoEnd()
{
//设置自动换行
ui->textEdit_SEND->setFocus();
// 光标移动到最后, 并设置拥有焦点
QTextCursor textcusor = ui->textEdit_SEND->textCursor();
textcusor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
ui->textEdit_SEND->setTextCursor(textcusor);
ui->textEdit_SEND->setFocus(Qt::MouseFocusReason);
}
void ChatWidget::on_pushButtot_CLEAR_clicked()
{
ui->textEdit_RECV->clear();
ui->textEdit_SEND->clear();
}
一、服务器端程序放到Linux系统下使用make编译
二、将编译生成的目标文件放到阿里服务器下执行:nohup ./server &
三、运行客户端,修改房间号和昵称登录。