Linux开发|一步一步学习Unix编程[2]——迭代服务器

【Linux开发|一步一步学习Unix编程[2]——迭代服务器】转载请注明t1234xy4原创:http://blog.csdn.net/t1234xy4/article/details/51925011
1、迭代服务器 所谓迭代服务器就是处理完一个客服端请求后,接着再处理第二个客服端请求,如果没有请求服务器将阻塞在accept处,直到有请求传来。
2、自定义头文件
在编代码前,需要先介绍自定义的一个头文件:MyIncludding.h

/* * MyIncluding.h * *Created on: Jul 11, 2016 *Author: ubuntu */#ifndef HEADER_MYINCLUDING_H_ #define HEADER_MYINCLUDING_H_#include #include #include #include #include #include #include #include #include #include #include #defineMAXLINE 1024 #defineFIFO_MODE (S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH)#define SERV_PORT9877 #define SAstruct sockaddr #define LISTENQ1024#endif /* HEADER_MYINCLUDING_H_ */

此处定义了服务器的监听端口SERV_PORT = 9877,服务器将使用这个端口监听。 同时定义了服务器监听的客户端请求的总个数 LISTENQ。LISTENQ包括了服务器端已建立连接的队列和未建立连接队列的总和。 已建立链接队列中保存了客户端与服务器端完成了TCP三路握手,这些链接处于ESTABLISHED状态,但没有服务器还没有accept此链接。 未建立连接队列中保存未客户端与服务器端还没有建立连接,客户的连接请求刚刚到达服务器,也就是三路握手的第一步。此时链接处于SYN_RCVD状态。如果三路握手正常完成将插入到已连接队列后。如果链接进入为建立连接队列超过一个RTT(往返时间)则被丢弃(因为重传机制,如果不丢弃将可能与该客户端建立两次链接或者更多)。
3、服务器端源码
/* * ServiceFork.cpp * *Created on: Jul 15, 2016 *Author: ubuntu */ #include #include "MyIncluding.h"using namespace std; char serv_ip[16] = "172.25.9.94"; //本地IP地址int main(int argc,char** argv) { int listenfd,connfd; pid_t childpid; struct sockaddr_in cliaddr,servaddr; bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET,serv_ip,&servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); listenfd = socket(AF_INET,SOCK_STREAM,0); int nbind = bind(listenfd,(SA *)&servaddr,sizeof(servaddr)); int nlisten = listen(listenfd,LISTENQ); while(1) { socklen_t cliaddrlen= sizeof(cliaddr); connfd = accept(listenfd,(SA *)&cliaddr,&cliaddrlen); if(connfd<0) cout <<"accept error!"< 0 ) cout<< "receive MSG:"<


此服务器端很简单,就与客户端建立连接,然后接受客户端传来的消息打印出来。 那么客户端应该做的事是与服务器建立连接,然后传一条消息过去。
4、客户端代码 为了便于扩展,我将客户端封装为一个SimClient类: SimClient.h
/* * SimClient.h * *Created on: Jul 13, 2016 *Author: ubuntu */#ifndef SIMCLIENT_H_ #define SIMCLIENT_H_#include "MyIncluding.h" #include "IOoperater.h" #include #include using namespace std; class SimClient {public: SimClient(); bool virtual connectServer(); virtual bool run(); void setClientId(int i){_clientId = i ; }

virtual bool stopRunning(); virtual bool reRun(); virtual ~SimClient(); protected: int sockfd; char* buf; struct sockaddr_in serviceaddr; int _clientId; }; #endif /* SIMCLIENT_H_ */



SimClient.cpp
/* * SimClient.cpp * *Created on: Jul 13, 2016 *Author: ubuntu */#include "SimClient.h"SimClient::SimClient():sockfd(-1),_clientId(-1){ // TODO Auto-generated constructor stub buf = new char[1]; strcpy(buf,"\0"); }bool SimClient::connectServer() { sockfd = socket(AF_INET,SOCK_STREAM,0); bzero(&serviceaddr,sizeof(serviceaddr)); serviceaddr.sin_family = AF_INET; char mySERV_IP[16] ="172.25.9.94"; inet_pton(AF_INET,mySERV_IP,&serviceaddr.sin_addr); //serviceaddr.sin_addr = htonl(SERV_IP); serviceaddr.sin_port = htons(SERV_PORT); int connectret; connectret = connect(sockfd,(SA *)&serviceaddr,sizeof(serviceaddr)); if(connectret<0) { cout << "connection error,errno="<

客户端调用入口:
//============================================================================ // Name: SimClient.cpp // Author: Tian // Version: // Copyright: Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================#include #include "SimClient.h" using namespace std; int main() { cout << "!!!!!!thread Test is running!!!!!!" << endl; sleep(1); SimClient *thread = new SimClient; thread->setThreadId(i); if (!thread->connectServer()) { cout << "thread "<< i << "failed!"<getThreadId()<run(); cout << thread->getThreadId() <<" shutdown !"; delete thread; return 0; }


总结: 服务端:socket()->bind()->listen()->accept()(阻塞)->read() 客户端:socket()->connect()->write() 结果是服务器端收到客服端的Id以及时间信息。

    推荐阅读