[c++]socket的简单实现

socket使用的demo(并没有设置非阻塞)

server:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h> 

#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>                                                                                                                                                                                
#include <pthread.h>
#include <string>
using namespace std;

# define BUFFER_SIZE 1001


int deal_new_conn(int* p_connfd, struct sockaddr* p_req_addr,socklen_t* p_addr_len);

int main(int argc, char *argv[])
{
	// 生成socket的地址 (ip port等)
	char nAddr[20] = "127.0.0.1"; 	// 指定ip
	int nPort = 9012;				// port
	struct in_addr addr;
	if (inet_aton("127.0.0.1", &addr) < 0) //得到网络字节序的IP
	{
		printf("[ERROR] addr %s:%d is invalid\n", nAddr, nPort);
		return -1;
	}
	struct sockaddr_in serv_addr; 
	memset(&serv_addr, '0', sizeof(serv_addr)); //地址初始化清空
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = addr.s_addr;
	serv_addr.sin_port = htons(nPort); 

	// 生成监听的socket_fd (file describe)
	int listenfd = 0, connfd = 0;
//	listenfd = socket(AF_INET, SOCK_STREAM  | SOCK_NONBLOCK, 0); // 非阻塞  这里设置noblock后accept就为非阻塞函数,accpt不到就返回-1
	listenfd = socket(AF_INET, SOCK_STREAM , 0); //生成socket

	// 绑定fd socket
	if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
	{
		printf("[ERROR] bind error!");
		return -1;
	}

	// 开始监听 fd
	if(listen(listenfd, 10) == -1)  // 设置连接队列的长度 为 10
	{
		printf("[ERROR] listen return false;");
		return 0;
	}

	printf("start waiting connect.\n");
	while(1)
	{
		//收到请求
		struct sockaddr req_addr = { 0 };
		socklen_t in_addr_len = sizeof (req_addr);
		// 从监听的fd的队列中取一个接收到的connect, 返回这个connect的fd
		connfd = accept(listenfd, &req_addr, &in_addr_len); // 接受到一个connect 返回fd
		printf("\n\n=======\nnew client connected.\n");
		deal_new_conn(&connfd, &req_addr, &in_addr_len);
	}

}  // server.c 服务端


int deal_new_conn(int* p_connfd, struct sockaddr* p_req_addr,socklen_t* p_addr_len)
{
	printf("start deal_new_conn...\n");
	// 收到请求后返回数据的buffer
	char sendBuff[1025];
	memset(sendBuff, '0', sizeof(sendBuff)); 

	int connfd = *p_connfd;
	struct sockaddr req_addr = *p_req_addr;
	socklen_t addr_len = *p_addr_len;
	// 设置非阻塞
//	int flags = fcntl(connfd, F_GETFL);
//	fcntl( connfd, F_SETFL, flags|O_NONBLOCK);
	// 取请求来源的ipport
	char hbuf[100], sbuf[100];
	if (getnameinfo(&req_addr, addr_len, hbuf, sizeof(hbuf), sbuf,
				sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
		    printf("host=%s, serv=%s\n", hbuf, sbuf);

	// 读请求内容多次读
	char recbuff[BUFFER_SIZE + 1];
	string rec;
	printf("===start read_data\n");
	for(;;)
	{
		int result_len = read(connfd,recbuff, BUFFER_SIZE);
//		if(result_len == -1 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
//		{
//			usleep(1);
//			printf("|%d", result_len);
//			continue;
//		}
		if(result_len > 0)
		{
			recbuff[result_len] = '\0';
			rec += recbuff;
			if(result_len != BUFFER_SIZE) 
			{
				printf("(break result_len != BUFFER_SIZE)\n");
				break;
			}
			printf("(continue)\n");
			continue;
		}
		printf("(break result_len <=0 )\n");
		break;
	}
	printf("[size:%d] ret:|%s|\n",rec.size(),  rec.c_str());
	printf("===end read_data\n");
	
	// 处理数据
	sleep(3); //阻塞三秒
	time_t ticks; 
	ticks = time(NULL);		// 返回当前时间
	snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks)); 	// 把结果输入到返回数据的buffer

	// 返回数据
	write(connfd, sendBuff, strlen(sendBuff)); 							// 写入返回数据
	close(connfd); //关闭当前连接
	printf("end deal_new_conn...\n");
	return 0;
}

server代码有点问题,如果read的内容刚好是buffer的整数倍时,会卡在最后一次read,,还没找到问题,,不过问题不大,socket常跟epoll共同使用,会设置为非阻塞, 循环读的方式会改变不会有这种问题。

client就比较简单了

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<errno.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<netdb.h>  
#include <sys/stat.h>
#include <fcntl.h>
#include<arpa/inet.h>
# include <unistd.h>
  
#define MAXLINE 4096  
  
  
int main(int argc, char** argv)  
{  
	int sockfd, n,rec_len;  
	char recvline[4096], sendline[4096]="qwertqwert1";  
	char buf[MAXLINE];  
	struct sockaddr_in servaddr;  
  
  
	if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){  
		printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);  
		exit(0);  
		}  
  
  
	memset(&servaddr, 0, sizeof(servaddr));  
	servaddr.sin_family = AF_INET;  
	servaddr.sin_port = htons(9012);  
	if( inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0 ){  
		printf("inet_pton error for 127.0.0.1\n");  
		exit(0);  
		}  
  
  
	if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ){  
		printf("connect error: %s(errno: %d)\n",strerror(errno),errno);  
		exit(0);  
		}  
  
  
	printf("send msg to server: \n");  
//	fgets(sendline, 4096, stdin);  
	if( send(sockfd, sendline, strlen(sendline), 0) < 0 )  
	{  
		printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);  
		exit(0);  
		}  
	if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) {  
		   perror("recv error");  
		   exit(1);  
		}  
	buf[rec_len]  = '\0';  
	printf("Received : %s ",buf);  
	close(sockfd);  
	exit(0);  
}  

参考链接:http://www.cnblogs.com/jiangzhaowei/p/8261174.html

猜你喜欢

转载自blog.csdn.net/sszzyzzy/article/details/89880013