linux c编程 TCP实例以及优化

来源:互联网 发布:算法导论最新版 编辑:程序博客网 时间:2024/05/05 12:14

文章代码来自于《嵌入式linux应用程序开发 标准教程》

第一个实例实现了服务器和客户端的TCP通信

第二个实例是在第一个的基础上使用了select函数实现多路复用 而不是一直阻塞


服务器代码

/*server.c*/#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <unistd.h>#include <netinet/in.h>#define PORT4321#define BUFFER_SIZE1024#define MAX_QUE_CONN_NM5int main(){struct sockaddr_in server_sockaddr, client_sockaddr;int sin_size, recvbytes;int sockfd, client_fd;char buf[BUFFER_SIZE];/*建立socket连接*/if ((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){perror("socket");exit(1);}printf("Socket id = %d\n",sockfd);/*设置sockaddr_in 结构体中相关参数*/server_sockaddr.sin_family = AF_INET;server_sockaddr.sin_port = htons(PORT);server_sockaddr.sin_addr.s_addr = INADDR_ANY;bzero(&(server_sockaddr.sin_zero), 8);int i = 1;/* 使得重复使用本地地址与套接字进行绑定 */setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));/*绑定函数bind*/if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr))== -1){perror("bind");exit(1);}printf("Bind success!\n");/*调用listen函数*/if (listen(sockfd, MAX_QUE_CONN_NM) == -1){perror("listen");exit(1);}printf("Listening....\n");/*调用accept函数,等待客户端的连接*/if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size)) == -1){perror("accept");exit(1);}/*调用recv函数接收客户端的请求*/memset(buf , 0, sizeof(buf));if ((recvbytes = recv(client_fd, buf, BUFFER_SIZE, 0)) == -1){perror("recv");exit(1);}printf("Received a message: %s\n", buf);close(sockfd);exit(0);}


客户端代码



/*client.c*/#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <unistd.h>#include <netdb.h>#include <netinet/in.h>#define PORT4321#define BUFFER_SIZE 1024int main(int argc, char *argv[]){int sockfd, sendbytes;char buf[BUFFER_SIZE];struct hostent *host;struct sockaddr_in serv_addr;if(argc < 3){fprintf(stderr,"USAGE: ./client Hostname(or ip address) Text\n");exit(1);}/*地址解析函数*/if ((host = gethostbyname(argv[1])) == NULL){perror("gethostbyname");exit(1);}memset(buf, 0, sizeof(buf));sprintf(buf, "%s", argv[2]);/*创建socket*/if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){perror("socket");exit(1);}/*设置sockaddr_in 结构体中相关参数*/serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);serv_addr.sin_addr = *((struct in_addr *)host->h_addr);bzero(&(serv_addr.sin_zero), 8);/*调用connect函数主动发起对服务器端的连接*/if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1){perror("connect");exit(1);}/*发送消息给服务器端*/if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1){perror("send");exit(1);}close(sockfd);exit(0);}



下面是优化后的服务器

/* net_select.c */#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <sys/ioctl.h>#include <unistd.h>#include <netinet/in.h>#define PORT4321#define MAX_QUE_CONN_NM5#define MAX_SOCK_FDFD_SETSIZE#define BUFFER_SIZE1024int main(){struct sockaddr_in server_sockaddr, client_sockaddr;int sin_size, count;fd_set inset, tmp_inset;int sockfd, client_fd, fd;char buf[BUFFER_SIZE];if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket");exit(1);}server_sockaddr.sin_family = AF_INET;server_sockaddr.sin_port = htons(PORT);server_sockaddr.sin_addr.s_addr = INADDR_ANY;bzero(&(server_sockaddr.sin_zero), 8);int i = 1;/* 使得重复使用本地地址与套接字进行绑定 */setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1){perror("bind");exit(1);}if(listen(sockfd, MAX_QUE_CONN_NM) == -1){perror("listen");exit(1);}printf("listening....\n");/*将调用socket函数的描述符作为文件描述符*/FD_ZERO(&inset);FD_SET(sockfd, &inset);while(1){tmp_inset = inset;sin_size=sizeof(struct sockaddr_in);memset(buf, 0, sizeof(buf));/*调用select函数*/if (!(select(MAX_SOCK_FD, &tmp_inset, NULL, NULL, NULL) > 0)){perror("select");close(sockfd);exit(1);}for (fd = 0; fd < MAX_SOCK_FD; fd++){if (FD_ISSET(fd, &tmp_inset) > 0) {if (fd == sockfd){ /* 服务端接收客户端的连接请求 */if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size))== -1){perror("accept");exit(1);}FD_SET(client_fd, &inset);printf("New connection from %d(socket)\n", client_fd);}else /* 处理从客户端发来的消息 */{if ((count = recv(fd, buf, BUFFER_SIZE, 0)) > 0){printf("Received a message from %d: %s\n", fd, buf);}else{close(fd);FD_CLR(fd, &inset);printf("Client %d(socket) has left\n", fd);}}} /* end of if FD_ISSET*/ } /* end of for fd*/} /* end if while while*/close(sockfd);exit(0);}

原创粉丝点击