一步一步学习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 

#define  MAXLINE 1024
#define  FIFO_MODE (S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH)

#define SERV_PORT 		9877
#define SA  			struct sockaddr
#define LISTENQ         1024

#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!"<		else{
			char buff[1024];
			int nread = read(connfd,buff,sizeof(buff));
			if( nread > 0 )
				cout<< "receive MSG:"<	close(connfd);
		}
	}
}

此服务器端很简单,就与客户端建立连接,然后接受客户端传来的消息打印出来。
那么客户端应该做的事是与服务器建立连接,然后传一条消息过去。

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="<	time_t ticks = time(NULL);
	snprintf(msg,sizeof(msg),"client %d access at: %.24s",_clientId,ctime(&ticks));
	int nwrite = write(sockfd,msg,strlen(msg));
	if(nwrite < 0)
		cout << "Message send failure ************"<	else
		cout << "Message: "<
客户端调用入口:
//============================================================================
// 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以及时间信息。

你可能感兴趣的:(Linux开发,网络编程)