QT 网络编程三(TCP版)
QT客户端
//widget.h
#ifndef WIDGET_H
#define WIDGET_H #include <QWidget>
#include <QTcpSocket>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QCloseEvent>
#include <QTextBrowser> class Widget : public QWidget
{
Q_OBJECT public:
Widget(QWidget *parent = );
~Widget();
private:
QTcpSocket *tcpsocket;
QPushButton *btn1,*btn2;
QLineEdit *edit1,*edit2,*edit3;
QLabel *label1,*label2,*label3;
QTextBrowser *textb; void closeEvent(QCloseEvent *event);
private slots:
void btn1_click();
void btn2_click();
void myrecvdata();
}; #endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QHostAddress> Widget::Widget(QWidget *parent)
: QWidget(parent)
{
tcpsocket=new QTcpSocket(this);
btn1=new QPushButton(tr("连接"));
btn2=new QPushButton(tr("发送"));
connect(btn1,SIGNAL(clicked()),this,SLOT(btn1_click()));
connect(btn2,SIGNAL(clicked()),this,SLOT(btn2_click()));
edit1=new QLineEdit();
edit2=new QLineEdit();
edit3=new QLineEdit();
label1=new QLabel(tr("IP地址:"));
label2=new QLabel(tr("端口号:"));
label3=new QLabel(tr("消息内容:"));
textb=new QTextBrowser();
QHBoxLayout *lay1=new QHBoxLayout();
lay1->addWidget(label1);
lay1->addWidget(edit1);
lay1->addWidget(label2);
lay1->addWidget(edit2);
lay1->addWidget(btn1);
QHBoxLayout *lay2=new QHBoxLayout();
lay2->addWidget(label3);
lay2->addWidget(edit3);
lay2->addWidget(btn2);
QHBoxLayout *lay4=new QHBoxLayout();
lay4->addWidget(textb);
QVBoxLayout * lay3=new QVBoxLayout(this);
lay3->addLayout(lay1);
lay3->addLayout(lay2);
lay3->addLayout(lay4);
/*接收数据*/
connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(myrecvdata()));
} //连接
void Widget::btn1_click()
{
/*禁用按钮,值是false*/
btn1->setEnabled(false);
//获取IP地址
QString ipaddr=edit1->text();
edit1->setEnabled(false);
//获取端口号
QString port=edit2->text();
edit2->setEnabled(false);
QHostAddress * serverip=new QHostAddress();
serverip->setAddress(ipaddr);
tcpsocket->connectToHost(*serverip,port.toInt());
//释放socket连接
delete serverip;
} //发送
void Widget::btn2_click()
{
QString strtext=edit3->text();
if(!strtext.isEmpty())
tcpsocket->write(strtext.toStdString().data());
/*清空输入框*/
edit3->clear();
/*设置输入框重新获得焦点*/
edit3->setFocus();
} //接收消息
void Widget::myrecvdata()
{
char buf[]={};
/*bytesAvailable()表示有效数据*/
while(tcpsocket->bytesAvailable()>)
{
memset(buf,,sizeof(buf));
tcpsocket->read(buf,sizeof(buf));
textb->append(buf);
//QMessageBox::information(this,"消息",buf);
}
} //关闭
void Widget::closeEvent(QCloseEvent *event)
{
if(QMessageBox::question(this,"提示","你确定要退出程序吗?",QMessageBox::Yes|QMessageBox::No,QMessageBox::No)==QMessageBox::Yes)
{
event->accept();
}else
{
event->ignore();
}
} Widget::~Widget()
{ }
Linux服务器端
//pub.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h> #define MAXPondNum 100 #ifdef __cplusplus
extern "C"
{
#endif //create socket
int create_socket(int port); //set noblock
int setnonblock(int st); //select
int open_select(int st); #ifdef __cplusplus
extern "C"
}
#endif
//pub.c
#include "pub.h" //create socket
int create_socket(int port)
{
if (port <= )
{
printf("create_socket() param not correct!\n");
return -;
}
int st = socket(AF_INET, SOCK_STREAM, );
if (st < )
{
printf("socket() failed ! error message:%s\n", strerror(errno));
return -;
}
//reuse address
int on = ;
if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < )
{
printf("socket() failed ! error message:%s\n", strerror(errno));
close(st);
return -;
}
//bind
struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(st, (struct sockaddr *) &addr, sizeof(addr)) < )
{
printf("bind() failed ! error message:%s\n", strerror(errno));
close(st);
return -;
}
//listen
if (listen(st, ) < )
{
printf("listen() failed ! error message:%s\n", strerror(errno));
close(st);
return -;
}
return st;
} //set noblock
int setnonblock(int st)
{
if (st < )
{
printf("setnonblock() param not correct!\n");
return -;
}
int opts = fcntl(st, F_GETFL);
if (opts < )
{
printf("fcntl() failed ! error message:%s\n", strerror(errno));
return -;
}
opts = opts | O_NONBLOCK;
if (fcntl(st, F_SETFL, opts))
{
printf("fcntl() failed ! error message:%s\n", strerror(errno));
return -;
}
return opts;
} //net address to
int sockaddrtoa(const struct sockaddr_in *addr, char *ipaddr)
{
if (addr == NULL || ipaddr == NULL)
{
printf("sockaddrtoa() param not correct!\n");
return -;
}
unsigned char *p = (unsigned char *) &(addr->sin_addr.s_addr);
sprintf(ipaddr, "%u:%u:%u:%u", p[], p[], p[], p[]);
return ;
} //accept clinet
int accept_client(int st)
{
if (st < )
{
printf("accept_client() param not correct!\n");
return -;
}
struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
socklen_t len = sizeof(addr);
int client_st = accept(st, (struct sockaddr *) &addr, &len);
if (client_st < )
{
printf("accept() failed ! error message:%s\n", strerror(errno));
return -;
}
char ipstr[] = { };
sockaddrtoa(&addr, ipstr);
printf("accept by %s\n", ipstr);
return client_st;
} //recv message
int recv_message(int st)
{
if (st < )
{
printf("accept_client() param not correct!\n");
return -;
}
char buf[]={};
int rc=recv(st,buf,sizeof(buf),);
if(rc<)
{
printf("recv() failed ! error message:%s\n",strerror(errno));
return -;
}else if(rc==)
{
/*这里需要判断客户端是不是关闭连接了*/
printf("client is closed!\n");
return -;
}
printf("%s\n",buf);
//发送接收信息
memset(buf,,sizeof(buf));
strcpy(buf,"server have recved !\n");
if(send(st,buf,sizeof(buf),)<)
{
printf("send() failed ! error message:%s\n",strerror(errno));
return -;
}
return ;
} //select
int open_select(int st)
{
if (st < )
{
printf("open_select() param not correct!\n");
return -;
}
int i = ;
/*池子中只存放客户端socket*/
int socketpond[MAXPondNum] = { };
/*
* 注意int socketpond[MAXPondNum] = { -1 };
* 改写法并不能将所有元素初始化为-1,只有0这种唯一特例
* */
for(i=;i<MAXPondNum;i++)
{
socketpond[i]=-;
}
/*定义事件数组中socket最大的值*/
int maxfd = ;
/*准备监听事件数组结构*/
fd_set allsocket;
while ()
{
/*清空有消息的事件数组*/
FD_ZERO(&allsocket);
/*将服务器socket直接放入事件数组中*/
FD_SET(st, &allsocket);
/*假设服务器socket是事件数组中最大的*/
maxfd = st;
/*遍历现有socket池,找出最大的socket,将所有的socket添加到事件数组中*/
for (i = ; i < MAXPondNum; i++)
{
if (socketpond[i] != -)
{
FD_SET(socketpond[i], &allsocket);
if (socketpond[i] > maxfd)
{
maxfd = socketpond[i];
}
}
}
int events = select(maxfd + , &allsocket, NULL, NULL, NULL);
if (events < )
{
printf("select() failed ! error message:%s\n", strerror(errno));
break;
}
/*
* 猜想:当两个客户端同时连接到服务器时,select是如何处理服务器socket事件的呢
* 我认为一个服务器端socket只能处理一个客户端连接请求
* 事件数组中只有一个服务器socket,这个服务器socket只会处理一个客户端连接请求,
* 而此时另外一个客户端请求会在下次的select事件数组中被处理
* */
/*先处理服务器socket特殊处理*/
if (FD_ISSET(st, &allsocket))
{
printf("accept client!\n");
//accept
int client_st = accept_client(st);
if (client_st < )
{
break;
}
//set nonblock
if (setnonblock(client_st) < )
{
break;
}
for (i = ; i < MAXPondNum; i++)
{
if (socketpond[i] == -)
{
socketpond[i] = client_st;
break;
}
}
if (i == MAXPondNum)
{
printf("服务端连接池已满!\n");
close(client_st);
}
}
for (i = ; i < MAXPondNum; i++)
{
if (socketpond[i] < )
{
continue;
}
if (FD_ISSET(socketpond[i], &allsocket))
{
//接收客户端发送消息
if(recv_message(socketpond[i])<)
{
//接收客户端消息出错
//关闭客户端
close(socketpond[i]);
//从服务器端socket池子中将该socket清除
socketpond[i]=-;
}
/*需要处理的事件数减一*/
events--;
}
if(events<)
{
break;
}
}
}
return ;
}
//mserver.c
//服务器端
#include "pub.h" int main(int arg,char *args[])
{
if(arg<)
{
printf("please print one param!\n");
return -;
}
int port=atoi(args[]);
int listen_st=create_socket(port);
if(listen_st<)
return -;
if(setnonblock(listen_st)<)
goto END;
open_select(listen_st);
END:close(listen_st);
return ;
}
.SUFFIXES:.c .o
CC=gcc
SRCS=mserver.c\
pub.c
OBJS=$(SRCS:.c=.o)
EXEC=mser
start:$(OBJS)
$(CC) -o $(EXEC) $(OBJS)
@echo "-------OK--------"
.c.o:
$(CC) -g -Wall -o $@ -c $<
clean:
rm -f $(OBJS)
rm -f $(EXEC)

QT 网络编程三(TCP版)的更多相关文章
- c++学习书籍推荐《C++ GUI Qt 4编程(第2版)》下载
下载地址:点我 百度云及其他网盘下载地址:点我 编辑推荐 <C++ GUI Qt 4编程(第2版)>讲授的大量Qt4编程原理和实践,都可以轻易将其应用于Qt4.4.Qt4.5及后续版本的Q ...
- C#网络编程之---TCP协议的同步通信(二)
上一篇学习日记C#网络编程之--TCP协议(一)中以服务端接受客户端的请求连接结尾既然服务端已经与客户端建立了连接,那么沟通通道已经打通,载满数据的小火车就可以彼此传送和接收了.现在让我们来看看数据的 ...
- 嵌入式linux的网络编程(1)--TCP/IP协议概述
嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- 【网络编程1】网络编程基础-TCP、UDP编程
网络基础知识 网络模型知识 OSI七层模型:(Open Systems Interconnection Reference Model)开放式通信系统互联参考模型,是国际标准化组织(ISO)提出的一个 ...
- python网络编程05 /TCP阻塞机制
python网络编程05 /TCP阻塞机制 目录 python网络编程05 /TCP阻塞机制 1.什么是拥塞控制 2.拥塞控制要考虑的因素 3.拥塞控制的方法: 1.慢开始和拥塞避免 2.快重传和快恢 ...
- Linux网络编程(三)
Linux网络编程(三) wait()还是waitpid() Linux网络编程(二)存在客户端断开连接后,服务器端存在大量僵尸进程.这是由于服务器子进程终止后,发送SIGCHLD信号给父进程,而父进 ...
- Qt网络编程QTcpServer和QTcpSocket的理解
前一段时间通过调试Qt源码,大致了解了Qt的事件机制.信号槽机制.毕竟能力和时间有限.有些地方理解的并不是很清楚. 开发环境:Linux((fedora 17),Qt版本(qt-everywhere- ...
- 【转载】[基础知识]【网络编程】TCP/IP
转自http://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=27043 [基础知识][网络编程]TCP/IP iooops 胖友们楼主我又 ...
随机推荐
- CSS3 background-size属性
请复制粘贴,图片请自带 <!DOCTYPE html > <html > <head> <meta charset="utf-8"> ...
- 万能面试问题大全,教你怎么回答,怎么拿下offer
一.你对薪资的要求? 回答提示: 说实话,大家找工作,都希望找个高薪的,那我们如何和公司去谈薪酬呢?如果你对薪酬的要求太低,那显然贬低自己的能力:如果你对薪酬的要求太高,那又会显得你分量过重,公司受用 ...
- sql server 2005导出数据到oracle
一. 在sql server下处理需要导出的数据库 1. 执行以下sql,查出所有'float'类型的字段名,手动将float类型改为decimal(18,4). select 表名=d.name,字 ...
- AngularJS服务
在使用AngularJS的路由管理和控制视图加载的时候,当新的视图加载进来,原有视图的控制器会被销毁,这是出于内存占用和性能的考虑.服务提供了一种能在应用的整个生命周期内保持和共享数据的方法,它能够在 ...
- node.js学习资料
Node.js 入门 <汇智网 Node.js 课程> <快速搭建 Node.js 开发环境以及加速 npm> http://fengmk2.com/blog/2014/03/ ...
- Python Select 解析
首先列一下,sellect.poll.epoll三者的区别 select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select ...
- MMORPG大型游戏设计与开发(客户端架构 part15 of vegine)
一个接口需要统一的派生接口,这样做的好处在于能够统一的进行管理.我所知的脚本语言中,接口有多重接口,也还有所谓的虚基类,这些都是方便类的管理.在vengine(微引擎)中,统一的的接口管理为kerne ...
- Java JDBC高级特性
1.JDBC批处理 实际开发中需要向数据库发送多条SQL语句,这时,如果逐条执行SQL语句,效率会很低,因此可以使用JDBC提供的批处理机制.Statement和PreparedStatemen都实现 ...
- 编写 Unity Editor 插件
Editor Style Viewer 在开发过程中,我喜欢编写一些辅助的Editor插件,方便在游戏开发过程进行调试. 下面是摘自Asset Store的一个查看Unity 默认GUI样式的小工具 ...
- 升级Flash Builder 4.6中的Flash Player版本
测试有效 本人按此方法升级到了flash player 15 Adobe自发布Flash Builder 4.6后,就暂停了Flash Builder新版本的发布.但AIR和FlashPlayer版本 ...