为什么客户端可以向服务器发送信息,而服务器不能向客户端发送信息?
服务代码:
#include <QtGui>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <pthread.h>
#include <QTimer>
#include "server.h"
#define BUFFER_SIZE 256
#define ECHO_PORT 2029
pthread_t m_thread;
struct hostent *client_addr;
int sockfd,opt=1;
socklen_t* len;
int flag=0;
struct sockaddr_in cliaddr;
char recvbuf[BUFFER_SIZE];
char buffer[BUFFER_SIZE];
int ret =0;
void *recvThread(void *data);
server::server(QWidget *parent)
:QWidget(parent)
{
SandRtextEdit=new QTextEdit;
SendPushButton=new QPushButton(tr("&Send"));
IpLineEdit=new QLineEdit("127.0.0.1");
IpLineEdit->setFocus(Qt::BacktabFocusReason);
textLineEdit=new QLineEdit;
IpLabel=new QLabel(tr("Ip:"));
IpLabel->setBuddy(IpLineEdit);
QHBoxLayout *firstLayout=new QHBoxLayout;
firstLayout->addWidget(IpLabel);
firstLayout->addWidget(IpLineEdit);
QHBoxLayout *secondLayout=new QHBoxLayout;
secondLayout->addWidget(textLineEdit);
secondLayout->addWidget(SendPushButton);
QVBoxLayout *mainLayout=new QVBoxLayout;
mainLayout->addWidget(SandRtextEdit);
mainLayout->addLayout(firstLayout);
mainLayout->addLayout(secondLayout);
setLayout(mainLayout);
memset(buffer,0xff,sizeof(buffer));
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("ERROR opening socket");
return;
}
/* if((ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0)
{
perror("ERROR setsockopt");
return;
}
*/
//printf("%d",sockfd);
if(( client_addr=gethostbyname(IpLineEdit->text().toUtf8().data())) == NULL)
{
herror("gethostbyname. ");
return;
}
memset(&cliaddr, 0, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr =htonl(INADDR_ANY);
cliaddr.sin_port = htons((uint16_t)ECHO_PORT);
if ((ret = bind(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr))) < 0)
{
perror("ERROR on binding");
return;
}
QTimer *m_DispTimer=new QTimer(this);
connect(m_DispTimer,SIGNAL(timeout()),this,SLOT(handleDispTimer()));
m_DispTimer->start(1000);
pthread_create(&m_thread,NULL,recvThread,NULL);
connect(SendPushButton,SIGNAL(clicked()),this,SLOT(buttonClicked()));
}
void *recvThread(void *data)
{
qDebug("create Thread succese");
while(1)
{
// len = (socklen_t*)sizeof(cliaddr);
if((ret=recvfrom(sockfd,recvbuf,sizeof(recvbuf)-1,0,NULL,NULL))>0)
{
perror("recv fail");
}
qDebug("recv succese");
recvbuf[ret]=0;
flag=1;
usleep(1000);
}
}
void server::handleDispTimer()
{
if(1==flag)
{
flag=0;
SandRtextEdit->append(QString(recvbuf));
}
}
void server::buttonClicked()
{
qDebug("button clicked");
int ret=0;
strcpy(buffer,textLineEdit->text().toUtf8().data());
if((ret=sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr *)&cliaddr,sizeof(cliaddr)))<0)
{
perror("ERROR writing to socket");
}
qDebug("send succese");
SandRtextEdit->append(buffer);
}
客户端代码:
#include <QtGui>
#include "clientchat.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <pthread.h>
#include <QTimer>
pthread_t m_thread;
int sockfd;
struct sockaddr_in servaddr;
struct hostent *server;
char recvbuf[100]={0};
int recvbyte=0;
int flag=0;
int ret=0;
void *recvThread();
#define ECHO_PORT 2029
void *recvThread(void *data);
ClientChat::ClientChat(QWidget *parent)
:QWidget(parent)
{
SandRtextEdit=new QTextEdit;
SendPushButton=new QPushButton(tr("&Send"));
IpLineEdit=new QLineEdit("127.0.0.1");
IpLineEdit->setFocus(Qt::BacktabFocusReason);
textLineEdit=new QLineEdit;
IpLabel=new QLabel(tr("Ip:"));
IpLabel->setBuddy(IpLineEdit);
QHBoxLayout *firstLayout=new QHBoxLayout;
firstLayout->addWidget(IpLabel);
firstLayout->addWidget(IpLineEdit);
QHBoxLayout *secondLayout=new QHBoxLayout;
secondLayout->addWidget(textLineEdit);
secondLayout->addWidget(SendPushButton);
QVBoxLayout *mainLayout=new QVBoxLayout;
mainLayout->addWidget(SandRtextEdit);
mainLayout->addLayout(firstLayout);
mainLayout->addLayout(secondLayout);
setLayout(mainLayout);
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("ERROR opening socket");
return;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
QTimer *m_DispTimer=new QTimer(this);
connect(m_DispTimer,SIGNAL(timeout()),this,SLOT(handleDispTimer()));
m_DispTimer->start(1000);
ret=pthread_create(&m_thread,NULL,recvThread,NULL);
if(ret!=0)
{
perror("thread");
}
connect(SendPushButton,SIGNAL(clicked()),this,SLOT(buttonClicked()));
}
void *recvThread(void *data)
{
qDebug("create Thread succese");
while(1)
{
if(recvbyte=recvfrom(sockfd,recvbuf,sizeof(recvbuf)-1,0,NULL,NULL)>0)
{
perror("recv fail");
// break;
}
qDebug("recv succese");
recvbuf[recvbyte]='\0';
flag=1;
usleep(10000);
}
}
void ClientChat::handleDispTimer()
{
if(1==flag)
{
flag=0;
SandRtextEdit->append(QString(recvbuf));
}
}
void ClientChat::buttonClicked()
{
qDebug("button clicked");
int ret=0;
char buffer[100]={0};
if((server = gethostbyname(IpLineEdit->text().toUtf8().data())) == NULL)
{
herror("gethostbyname. ");
return;
}
qDebug("get host name succese");
servaddr.sin_addr.s_addr=*(unsigned int*)server->h_addr;
servaddr.sin_port = htons((uint16_t)ECHO_PORT);
strcpy(buffer,textLineEdit->text().toUtf8().data());
if((ret=sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr *)&servaddr,sizeof(servaddr)))<0)
{
perror("ERROR writing to socket");
}
qDebug("send succese");
SandRtextEdit->append(buffer);
}