重头开始嵌入式第三十二天(TCP多客户端模型)
1.多路IO
1.select
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{
//监听套接字
int listfd = socket(AF_INET,SOCK_STREAM,0 );
if(-1 ==listfd)
{
perror("socket");
exit(1);
}
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
bzero(&cli,sizeof(cli));
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr =inet_addr("127.0.0.1");
//man 7 socket
int on = 1;
setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
int ret = bind(listfd,(SA)&ser,sizeof(ser));
if(-1 ==ret)
{
perror("bind");
exit(1);
}
//建立连接的排队数
listen(listfd,3);
socklen_t len = sizeof(cli);
//1 create set
fd_set rd_set,tmp_set;
FD_ZERO(&rd_set);
FD_ZERO(&tmp_set);
//2.add fd
FD_SET(listfd,&tmp_set);
int maxfd = listfd;
while(1)
{
rd_set = tmp_set;
select(maxfd+1,&rd_set,NULL,NULL,NULL);
int i = 0 ;
//通讯套接字
for(i = 0 ;i<maxfd+1;i++)
{
if(FD_ISSET(i,&rd_set) && i ==listfd)
{
int conn = accept(listfd,(SA)&cli,&len);
if(-1 == conn)
{
perror("accept");
// exit(1);
continue;
}
FD_SET(conn,&tmp_set);
if(conn>maxfd)
maxfd = conn;
}
if(FD_ISSET(i,&rd_set) && i!=listfd)
{
int conn = i ;
char buf[512]={0};
int rd_ret = recv(conn,buf,sizeof(buf),0);
if(rd_ret<=0)
{
FD_CLR(conn,&tmp_set);
close(conn);
printf("cli offline\n");
break;
}
//printf("cli:%s\n",buf);
time_t tm;
time(&tm);
sprintf(buf,"%s %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
}
}
close(listfd);
return 0;
}
2.epoll
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/epoll.h>
typedef struct sockaddr* (SA);
int add_fd(int epfd,int fd)
{
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd;
int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);
if(-1 == ret)
{
perror("add fd");
}
return ret;
}
int del_fd(int epfd,int fd)
{
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd;
int ret = epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);
if(-1 == ret)
{
perror("add fd");
}
return ret;
}
int main(int argc, char *argv[])
{
//监听套接字
int listfd = socket(AF_INET,SOCK_STREAM,0 );
if(-1 ==listfd)
{
perror("socket");
exit(1);
}
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
bzero(&cli,sizeof(cli));
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr =inet_addr("127.0.0.1");
//man 7 socket
int on = 1;
setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
int ret = bind(listfd,(SA)&ser,sizeof(ser));
if(-1 ==ret)
{
perror("bind");
exit(1);
}
//建立连接的排队数
listen(listfd,3);
socklen_t len = sizeof(cli);
struct epoll_event rev[10]={0};
//1 create set
int epfd = epoll_create(10);
if(-1 == epfd)
{
perror("epoll_create");
return 1;
}
// 2 .add fd
add_fd(epfd,listfd);
while(1)
{
//3 wait event
int ep_ret = epoll_wait(epfd,rev,10,-1);
int i = 0 ;
//4 find fd handle
for(i = 0 ;i<ep_ret;i++)
{
if(rev[i].data.fd == listfd)
{ //通讯套接字
int conn = accept(listfd,(SA)&cli,&len);
if(-1 == conn)
{
perror("accept");
continue;
}
add_fd(epfd,conn);
}
else
{
int conn = rev[i].data.fd;
char buf[512]={0};
int rd_ret = recv(conn,buf,sizeof(buf),0);
if(rd_ret<=0)
{
del_fd(epfd,conn);
close(conn);
break;
}
time_t tm;
time(&tm);
sprintf(buf,"%s %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
}
}
close(listfd);
return 0;
}
2.并发模型
1.进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
typedef struct sockaddr* (SA);
void handle(int num)
{
wait(NULL);
}
int main(int argc, char *argv[])
{
signal(SIGCHLD,handle);
//监听套接字
int listfd = socket(AF_INET,SOCK_STREAM,0 );
if(-1 ==listfd)
{
perror("socket");
exit(1);
}
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
bzero(&cli,sizeof(cli));
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr =inet_addr("127.0.0.1");
//man 7 socket
int on = 1;
setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
int ret = bind(listfd,(SA)&ser,sizeof(ser));
if(-1 ==ret)
{
perror("bind");
exit(1);
}
//建立连接的排队数
listen(listfd,3);
socklen_t len = sizeof(cli);
while(1)
{
//通讯套接字
int conn = accept(listfd,(SA)&cli,&len);
if(-1 == conn)
{
perror("accept");
//exit(1);
continue;
}
pid_t pid = fork();
if(0 == pid)
{
close(listfd);
while(1)
{
char buf[512]={0};
int rd_ret = recv(conn,buf,sizeof(buf),0);
if(rd_ret<=0)
{
printf("cli off line\n");
close(conn);
//break;
exit(1);
}
printf("cli:%s\n",buf);
time_t tm;
time(&tm);
sprintf(buf,"%s %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
}
else if (pid>0)
{
close(conn);
}
else
{
printf("fork");
continue;
}
}
close(listfd);
return 0;
}
2.线程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
typedef struct sockaddr* (SA);
void* th(void* arg)
{
pthread_detach(pthread_self());
int conn =* (int*)arg;
//sem_post();
while(1)
{
char buf[512]={0};
int rd_ret = recv(conn,buf,sizeof(buf),0);
if(rd_ret<=0)
{
printf("cli off line\n");
close(conn);
break;
}
printf("cli:%s\n",buf);
time_t tm;
time(&tm);
sprintf(buf,"%s %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
return NULL;
}
int main(int argc, char *argv[])
{
//监听套接字
int listfd = socket(AF_INET,SOCK_STREAM,0 );
if(-1 ==listfd)
{
perror("socket");
exit(1);
}
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
bzero(&cli,sizeof(cli));
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr =inet_addr("127.0.0.1");
//man 7 socket
int on = 1;
setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
int ret = bind(listfd,(SA)&ser,sizeof(ser));
if(-1 ==ret)
{
perror("bind");
exit(1);
}
//建立连接的排队数
listen(listfd,3);
socklen_t len = sizeof(cli);
while(1)
{
//通讯套接字
int conn = accept(listfd,(SA)&cli,&len);
if(-1 == conn)
{
perror("accept");
//exit(1);
continue;
}
pthread_t tid;
pthread_create(&tid,NULL,th,&conn);
//sem_wait();
// join();
// 确保th中,把conn保存到局部变量中
usleep(1000*5);
}
close(listfd);
return 0;
}
3.循环
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 8888
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// 创建服务器套接字
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// 绑定套接字到指定端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听连接
if (listen(server_fd, 3) < 0) {
perror("listen failed");
exit(EXIT_FAILURE);
}
while (1) {
// 接受新的连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
while (1) {
int valread = read(new_socket, buffer, BUFFER_SIZE);
if (valread <= 0) {
break;
}
printf("Received from client: %s\n", buffer);
send(new_socket, buffer, strlen(buffer), 0);
memset(buffer, 0, BUFFER_SIZE);
}
close(new_socket);
}
return 0;
}