前言
前几天写了一篇学习网络编程的总结,现在对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;
}