----------- MyChatROOM.pro -------------------------------- QT + =核心gui
greaterThan(QT_MAJOR_VERSION,4):QT + =小部件
TARGET = MyChatROOM TEMPLATE = app
LIBS + = -lwsock32
SOURCES + = main.cpp \ mainwindow.cpp
HEADERS + = mainwindow.h
FORMS + = mainwindow.ui
------ mainwindow.h ----------------------
命名空间Ui {
类MainWindow;
}
类MainWindow:public QMainWindow
{
Q_OBJECT
ChatRoomServer server;
公共:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
私人:
Ui::MainWindow *ui;
};
---------------- main.cpp中-----------------
int main(int argc,char * argv [])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
---------- ----------- mainwindow.cpp
MainWindow :: MainWindow(QWidget * parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
server.init();
}
主窗口::〜主窗口()
{
delete ui;
server.release();
}
--------------- ChatRoomServerr.h ------------
类ChatRoomServer
{
私人:
NetListener listener;
公共:
typedef std::list <NetStream> V_STREAM;
V_STREAM vStream;
公共:
void init()
{
listener.startListen(2345);
}
void doStream(NetStream& stream)
{
stream.totalRecv();
int pktID;
while (stream.checkRecv(pktID))
{
if (pktID == PKT_STR)
{
char buf[256];
stream.recv(buf, sizeof(buf));
V_STREAM::iterator pi = vStream.begin();
while (pi != vStream.end())
{
if (&(*pi) != &stream)
pi->send(buf);
++pi;
}
}
else if (pktID == PKT_CHAR)
{
char chr;
stream.recv(chr);
V_STREAM::iterator pi = vStream.begin();
while (pi != vStream.end())
{
if (&(*pi) != &stream)
pi->send(chr);
++pi;
}
}
else
{
assert(0);
}
}
stream.totalSend();
}
void work()
{
while (listener.doAccept())
{
vStream.resize(vStream.size() + 1);
listener.popAcceptSocket(vStream.back());
}
V_STREAM::iterator pi = vStream.begin();
while (pi != vStream.end())
{
doStream(*pi);
pi++;
}
}
void release()
{
}
};
----------------- net_stream.h ----------------------
enum {PKT_CHAR,PKT_INT,PKT_FLOAT,PKT_XY,PKT_STR};
类NetStream
{
私人:
SOCKET newSocket ;
bool bConnected ;
typedef std::vector <char> V_SEND_DATA ;
V_SEND_DATA vSendData ;
int curSendPos ;
V_SEND_DATA vRecvData ;
int curRecvPos ;
int curDataSize;
公共:
NetStream ():bConnected(false),newSocket(INVALID_SOCKET),curRecvPos(0)
{
}
~NetStream ()
{
close () ;
}
static void fnInit ()
{
WSADATA wsaData;
WORD version = MAKEWORD(2, 2) ;
WSAStartup (version, &wsaData) ;
}
static void fnRelease ()
{
WSACleanup () ;
}
bool isConnected ()const
{
return bConnected ;
}
void setAcceptSocket (SOCKET as)
{
close () ;
assert (newSocket == INVALID_SOCKET) ;
newSocket = as ;
u_long nonBlock = true ;
int r = ioctlsocket (newSocket,
FIONBIO, &nonBlock) ;
assert (r != SOCKET_ERROR) ;
bConnected = true ;
}
void startConnect (const char* ip, int port)
{
close () ;
assert (newSocket == INVALID_SOCKET) ;
newSocket = socket (AF_INET, SOCK_STREAM,
IPPROTO_TCP) ;
assert (newSocket != INVALID_SOCKET) ;
int i0, i1, i2, i3 ;
sscanf (ip, "%d.%d.%d.%d", &i0, &i1, &i2, &i3) ;
sockaddr_in connectAddress ;
memset (&connectAddress, 0, sizeof
(connectAddress)) ;
connectAddress.sin_family = AF_INET ;
connectAddress.sin_addr.S_un.S_un_b.s_b1 = i0 ;
connectAddress.sin_addr.S_un.S_un_b.s_b2 = i1 ;
connectAddress.sin_addr.S_un.S_un_b.s_b3 = i2 ;
connectAddress.sin_addr.S_un.S_un_b.s_b4 = i3 ;
connectAddress.sin_port = htons (port) ;
//設定non block mode
u_long nonBlock = true ;
int r = ioctlsocket (newSocket, FIONBIO, &nonBlock) ;
assert (r != SOCKET_ERROR) ;
r = connect (newSocket, (sockaddr*)&connectAddress,
sizeof (connectAddress)) ;
}
void checkConnected ()
{
if (newSocket != INVALID_SOCKET)
if (bConnected == false)
{
fd_set tmpSet ;
FD_ZERO(&tmpSet);
FD_SET(newSocket,&tmpSet);
timeval timeV ;
timeV.tv_sec = 0 ;
timeV.tv_usec = 100 ;
if (select (0, NULL, &tmpSet, NULL, &timeV) == 1)
{
bConnected = true ;
}
}
}
私人:
void sendBuf (const void* pData, int dataSize)
{
int oriSize = vSendData.size () ;
vSendData.resize (oriSize+dataSize) ;
const char* pSD = (const char*)pData ;
for (int i = 0; i<dataSize; i++)
vSendData[oriSize+i] = pSD[i] ;
}
公共:
void totalSend ()
{
if (isConnected () && vSendData.size () > 0)
{
const char* pData = &(vSendData[0]) ;
int dataSize = vSendData.size () ;
int r = ::send (newSocket, pData, dataSize, 0) ;
if (r != SOCKET_ERROR)
{
if (r < dataSize)
{
int leftSize = dataSize-r ;
for (int i = 0; i<leftSize; i++)
vSendData[i] = vSendData[i+r] ;
vSendData.resize (leftSize) ;
}else
{
vSendData.clear () ;
}
}else
{
r = WSAGetLastError () ;
if (r == WSAEWOULDBLOCK)
{
}else
{
close () ;
}
}
}
}
私人:
void beginSendBuf (int pktID)
{
curSendPos = vSendData.size () ;
int fakeSize = -1 ;
sendBuf (&fakeSize, sizeof (fakeSize)) ;
sendBuf (&pktID, sizeof (pktID)) ;
}
void endSendBuf ()
{
int pktSize = vSendData.size ()-curSendPos ;
int* pSize = (int*)(&(vSendData[curSendPos])) ;
*pSize = pktSize ;
}
公共:
void send(const char* chr)
{
if (isConnected())
{
beginSendBuf(PKT_STR);
sendBuf(chr,strlen(chr));
endSendBuf();
}
}
void send (const char& data)
{
if (isConnected ())
{
beginSendBuf (PKT_CHAR) ;
sendBuf (&data, sizeof (data)) ;
endSendBuf () ;
}
}
void send (const int& data)
{
if (isConnected ())
{
beginSendBuf (PKT_INT) ;
sendBuf (&data, sizeof (data)) ;
endSendBuf () ;
}
}
void send (const float& data)//送float
{
if (isConnected ())
{
beginSendBuf (PKT_FLOAT) ;
sendBuf (&data, sizeof (data)) ;
endSendBuf () ;
}
}
void sendXY (const float& x, const float& y)
{
if (isConnected ())
{
beginSendBuf (PKT_XY) ;
//真正的資料
sendBuf (&x, sizeof (x)) ;
sendBuf (&y, sizeof (y)) ;
endSendBuf () ;
}
}
void totalRecv ()
{
if (isConnected () == false)
return ;
if (curRecvPos > 0)
{
int leftSize = vRecvData.size ()-curRecvPos ;
for (int i = 0; i<leftSize; i++)
vRecvData[i] = vRecvData[curRecvPos+i] ;
vRecvData.resize (leftSize) ;
curRecvPos = 0 ;
}
while (true)
{
int oriSize = vRecvData.size () ;
const int TMP_RECV_SIZE = 1024*10 ;
vRecvData.resize (oriSize+TMP_RECV_SIZE) ;
char* pData = &(vRecvData[oriSize]) ;
int recvSize = ::recv (newSocket, pData, TMP_RECV_SIZE, 0) ;
if (recvSize > 0)
{
//有收到資料
if (recvSize < TMP_RECV_SIZE)
{
int extSize = TMP_RECV_SIZE-recvSize ;
vRecvData.resize (vRecvData.size ()-extSize) ;
break ;
}else
{
}
}else if (recvSize == 0)
{
//斷線了
close () ;
break ;
}else
{
vRecvData.resize (vRecvData.size ()-TMP_RECV_SIZE) ;
int r = WSAGetLastError () ;
if (r == WSAEWOULDBLOCK)
{
}else
{
close () ;
}
break ;
}
}
}
bool checkRecv (int &pktID)
{
int totalSize = vRecvData.size ()-curRecvPos ;
int recvSize = sizeof (int)+sizeof (int) ;//大小+ID
if (totalSize >= recvSize)
{
//可以取得pktSize+pktID
int* pData = (int*)(&(vRecvData[curRecvPos])) ;
int pktSize = *pData ;
curDataSize = pktSize - sizeof(int) - sizeof(int);
if (totalSize >= pktSize)
{
pData = (int*)(&(vRecvData[curRecvPos+sizeof (int)])) ;
pktID = *pData ;
curRecvPos += recvSize ;
return true ;
}else
{
return false ;
}
}else
{
return false ;
}
}
bool recv(char *buf, int bufSize)
{
int totalSize = vRecvData.size() - curRecvPos;
assert(bufSize >= curDataSize+1);
if (totalSize >= curDataSize)
{//資料足夠
char* pData = (char *)(&vRecvData[curRecvPos]);
for (int i = 0; i < curDataSize; i++)
buf[i] = pData[i];
buf[curDataSize] = 0;
curRecvPos += curDataSize;
return true;
}
else
assert(0);
return false;
}
bool recv (char &data)
{
int totalSize = vRecvData.size ()-curRecvPos ;
int recvSize = sizeof (data) ;
if (totalSize >= recvSize)
{
//資料足夠
char* pData = (char*)(&(vRecvData[curRecvPos])) ;
data = *pData ;
curRecvPos += recvSize ;
return true ;
}else
{
//資料不夠
assert(0);
return false ;
}
}
bool recv (int &data)
{
int totalSize = vRecvData.size ()-curRecvPos ;//有效資料的大小
int recvSize = sizeof (data) ;
if (totalSize >= recvSize)
{
int* pData = (int*)(&(vRecvData[curRecvPos])) ;
data = *pData ;
curRecvPos += recvSize ;
return true ;
}else
{
assert(0);
return false ;
}
}
bool recv (float &data)
{
int totalSize = vRecvData.size ()-curRecvPos ;//有效資料的大小
int recvSize = sizeof (data) ;
if (totalSize >= recvSize)
{
float* pData = (float*)(&(vRecvData[curRecvPos])) ;
data = *pData ;
curRecvPos += recvSize ;
return true ;
}else
{
assert(0);
return false ;
}
}
bool recvXY (float &x, float& y)
{
int totalSize = vRecvData.size ()-curRecvPos ;
int recvSize = sizeof (x)+sizeof (y) ;
if (totalSize >= recvSize)
{
float* pData = (float*)(&(vRecvData[curRecvPos])) ;
x = *pData ;
pData = (float*)(&(vRecvData[curRecvPos+sizeof (x)])) ;
y = *pData ;
curRecvPos += recvSize ;
return true ;
}else
{
assert(0);
return false ;
}
}
void close ()
{
if (newSocket != INVALID_SOCKET)
{
closesocket (newSocket) ;
newSocket = INVALID_SOCKET ;
bConnected = false ;
curRecvPos = 0 ;
}
}
};
类NetListener
{
私人:
SOCKET skt ;
typedef std::vector <SOCKET> V_ACCEPT_SOCKET ;
V_ACCEPT_SOCKET vAcceptSocket ;
公共:
void startListen (int port)
{
skt = socket (AF_INET, SOCK_STREAM,
IPPROTO_TCP) ;
assert (skt != INVALID_SOCKET) ;
u_long nonBlock = true ;
int r = ioctlsocket (skt, FIONBIO, &nonBlock) ;
assert (r != SOCKET_ERROR) ;
sockaddr_in serverAddress ;
memset (&serverAddress, 0, sizeof (serverAddress)) ;
serverAddress.sin_family = AF_INET ;
serverAddress.sin_addr.s_addr = INADDR_ANY ;
serverAddress.sin_port = htons (port) ;
r = bind (skt, (sockaddr*)&serverAddress,
sizeof (serverAddress)) ;
assert (r != SOCKET_ERROR) ;
r = listen (skt, SOMAXCONN) ;
assert (r != SOCKET_ERROR) ;
}
bool doAccept ()
{
while (true)
{
SOCKET newSocket = accept (skt, NULL, NULL) ;
if (newSocket != INVALID_SOCKET)
{
vAcceptSocket.push_back (newSocket) ;
}else
break ;
}
if (vAcceptSocket.size () > 0)
return true ;
else
return false ;
}
void popAcceptSocket (NetStream& ns)
{
assert (vAcceptSocket.size () > 0) ;
ns.setAcceptSocket (vAcceptSocket.front ()) ;
vAcceptSocket.erase (vAcceptSocket.begin ()) ;//刪除
}
/*
bool acceptStream (NetStream& ns)
{
SOCKET newSocket = accept (skt, NULL, NULL) ;
if (newSocket != INVALID_SOCKET)
{
ns.setAcceptSocket (newSocket) ;
return true ;
}else
return false ;
}
*/
};
答案 0 :(得分:0)
对不起!!我解决了。 重新安装Qt后,此问题不再出现! 也许MainGW之前没有安装过。