select网络编程实践

前言

前几天写了一篇学习网络编程的总结,现在对select实践一把,实现客户端向服务端发送一个字符串,服务端原样返回字符串到客户端。

服务端代码

/********************************
*从客户端接收数据然后返回给客户端
*********************************/
#include  <unistd.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <netinet/in.h>
#include  <arpa/inet.h>
#include <sys/select.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define SERVER_PORT		(12345)
#define BUF_LEN			(1024)

int g_server_fd = -1;

int start_server()
{
	struct sockaddr_in	servaddr;
	socklen_t socklen = sizeof(struct sockaddr_in);
	//socket 
	g_server_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (g_server_fd < 0)
	{
		printf("socket error.\n");
		return -1;
	}
	
	//bind
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(SERVER_PORT);
	
	if(bind(g_server_fd, (struct sockaddr*)&servaddr, socklen) == -1) {
		printf("bind error.\n");
        return -1;
    }
	
	//listen
	if (listen(g_server_fd, 1024) < 0)
	{
		printf("listen error.\n");
		return  -1;
	}
	return g_server_fd;
}


void handle_client(int * client_fds, int max_fds, fd_set* p_rset, fd_set* p_all_set)
{
    int nread;
    int i;
    char buf[BUF_LEN];
    for (i = 0; i< max_fds; i++) {
        if (client_fds[i] != -1) {
            if (FD_ISSET(client_fds[i], p_rset)) {
                nread = read(client_fds[i], buf, BUF_LEN);
                if (nread < 0) {
                    printf("read error.\n");
                    close(client_fds[i]);
                    FD_CLR(client_fds[i], p_all_set);
                    client_fds[i] = -1;
                    continue;
                }
                if (nread == 0) {
                    printf("client close the connection.\n");
                    close(client_fds[i]);
                    FD_CLR(client_fds[i], p_all_set);
                    client_fds[i] = -1;
                    continue;
                } 
				
                write(client_fds[i], buf, nread);
            }
        }
    }

}

int main(int argc, char ** argv)
{
	start_server();
	int cli_fds[FD_SETSIZE] = {-1};
	fd_set all_set, r_set;
	FD_ZERO(&all_set);
	FD_SET(g_server_fd, &all_set);
	int maxfd = g_server_fd;
	int cli_fd;
	int n_ready = 0;
	struct sockaddr_in	cliaddr;
	socklen_t socklen = sizeof(struct sockaddr_in);
	char buf[BUF_LEN] = {0};
	int i,nready;
	
	while (1)
	{
		r_set = all_set;
		n_ready = select(maxfd + 1 , &r_set, NULL, NULL, NULL);
		if (n_ready < 0)
		{
			printf("select error.\n");
			continue;
		}
		if (FD_ISSET(g_server_fd, &r_set)) {
            cli_fd = accept(g_server_fd, (struct sockaddr*)&cliaddr, &socklen);
            if (cli_fd < 0) {
                printf("accept error.\n");
                continue;
            }

            sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
            printf("%s\n",buf);
			
			for (i = 0; i< FD_SETSIZE; i++) {
                if (cli_fds[i] == -1) {
                    cli_fds[i] = cli_fd;
                    break;
                }
            }
            if (i == FD_SETSIZE) {
                printf("too many connection, more than %d\n", FD_SETSIZE);
                close(cli_fd);
                continue;
            }
            if (cli_fd > maxfd)
                maxfd = cli_fd;

            FD_SET(cli_fd, &all_set);
            if (--nready <= 0)
                continue;
		}
		handle_client(cli_fds, maxfd, &r_set, &all_set);
	}
	return 0;
}

客户端代码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
	unsigned short port = 12345;
	char *server_ip = "127.0.0.1";
 
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
	{
		perror("socket");
		exit(-1);
	}
	
	struct sockaddr_in server_addr;
	bzero(&server_addr,sizeof(server_addr)); 
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(port);
	inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
	
	int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if(err_log != 0)
	{
		printf("connect error.\n");
		close(sockfd);
		return -1;
	}
	char buf[1024] = {0};
	int max_fd;
	fd_set r_set;
	FD_ZERO(&r_set);
	int n, i=0;
	struct timeval timeout;
	timeout.tv_sec = 0;
	timeout.tv_usec =100;
	
	write(sockfd, "hello", 6);
	
	while (1)
	{
		FD_SET(sockfd, &r_set);
		max_fd = sockfd + 1;
		select(max_fd, &r_set, NULL, NULL, &timeout);
		if (FD_ISSET(sockfd, &r_set)) 
		{	
			if ( (n = read(sockfd, buf, 1024)) == 0) 
			{
				printf("cli will exit.\n");
				break;
			}
			else
			{
				printf("recv from  server:%s\n",buf);
			}
			write(sockfd, "hello1", 6);
		}

		i++;
		if (i > 5)
			break;
	}
 	close(sockfd);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值