本文共 4713 字,大约阅读时间需要 15 分钟。
搭建一个基于Linux系统的网络服务器,实现客户端数据的接收与转发。这篇文章将详细介绍服务器端的实现步骤及工作原理。
本节将介绍服务器端的开发流程,包括创建socket、监听客户端连接及接收并处理数据的过程。
#include#include #include #include #include #include #include #include #include
#define PORT_SERV 8888#define BUFFSIZE 1024char receiveBuff[BUFFSIZE] = { 0 };
int main() { int server_sockfd, client_sockfd; int server_len, client_len; struct sockaddr_in server_address; struct sockaddr_in client_address; int result; // 创建服务器端socket server_sockfd = socket(AF_INET, SOCK_STREAM, 0); server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl(INADDR_ANY); server_address.sin_port = htons(PORT_SERV); server_len = sizeof(server_address); bind(server_sockfd, (struct sockaddr *)&server_address, server_len); // 开始监听客户端连接 listen(server_sockfd, 5); // 初始化读取集合 // FD_ZERO(&readfds); FD_SET(server_sockfd, &readfds); printf("server running.\n"); fflush(stdout);
while(1) { int fd, nread; testfds = readfds; // 阻塞等待事件 result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); if (result < 1) { perror("server error : select() result < 1"); fflush(stdout); exit(1); } // 扫描文件描述符 for(fd = 0; fd < FD_SETSIZE; fd++) { if(FD_ISSET(fd, &testfds)) { // 处理服务器端socket if(fd == server_sockfd) { client_len = sizeof(client_address); client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_address, (socklen_t*)&client_len); FD_SET(client_sockfd, &readfds); printf("adding client on fd %d\n", client_sockfd); fflush(stdout); clientFDs.push_back(client_sockfd); } // 处理客户端socket else { // 获取接收缓冲区大小 ioctl(fd, FIONREAD, &nread); if(nread == 0) { close(fd); FD_CLR(fd, &readfds); printf("removing client on fd %d\n", fd); fflush(stdout); clientFDs.remove(fd); } else { read(fd, receiveBuff, nread); sleep(2); printf("client fd %d, receiveBuff :\n", fd); printf("%s\n", receiveBuff); fflush(stdout); clientFD_buff_map.insert(std::pair(fd, (std::string)receiveBuff)); memset(receiveBuff, 0, BUFFSIZE); ftruncate(fd, 0); lseek(fd, 0, SEEK_SET); } // 数据转发部分 std::map ::iterator it; std::list ::iterator listIt; for(listIt = clientFDs.begin(); listIt != clientFDs.end(); listIt++) { for(it = clientFD_buff_map.begin(); it != clientFD_buff_map.end(); it++) { if(it->first != *listIt) { cout << "client " << it->first << " -> " << "data from " << listIt->first << endl; write(*listIt, it->second.c_str(), it->second.length()); } } } clientFD_buff_map.clear(); } } }}
推荐搭建环境:
sudo apt-get install build-essential model-viewer libboost-dev libboost-system-dev
g++ -o server *.[等待编译完成]
./server
此时服务器已启动,等待客户端连接。
#include#include #include #include #include int main() { QApplication app(FALSE); TcpSocket *socket = new TcpSocket(); socket->connectToHost(QHostInfo::localhost(), 8888); QTextBrowser browser; browser.show(); return app.exec();}
void socketConnected() { socket-> ㅤ timeout(); connect(socket, &TcpSocket::readyRead, this, &MainWindow::onDataReceived);}void onDataReceived() { QString data = QString(socket->readAll()); // 显示或处理接收到的数据}
通过上述步骤,成功实现了从服务器到客户端的数据传输功能,具备发送和接收双向通信能力,用户可以根据需求在界面上进行数据展示或处理。
本文在实际应用中可能会遇到一些问题,例如网络连接异常或套接字阻塞等需要注意以下几点:
最后,服务器程序需要不断关注新连接申请,保持服务稳定性,同时处理客户端数据nection closure 以确保资源 finite.
转载地址:http://fqylz.baihongyu.com/