十八、Linux网络编程(二)
3.并发服务器
1.TCP多线程并发服务器
service_thread.c:
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define backlog 5
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"
void* client_data_handle(void *arg);
int main()
{
int fd = -1;
struct sockaddr_in sin;
//1.socket
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd < 0)
{
perror("socket");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SERV_IP);
// sin.sin_addr.s_addr = inet_addr(SERV_IP_ADDR);
sin.sin_addr.s_addr = INADDR_ANY;
/* if(inet_pton(AF_INET,SERV_IP_ADDR,sin.(void *)&sin_addr.s_addr) != 1)
{
perror("inet_pton");
exit(1);
}
*/
//2.bind
if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("bind");
exit(1);
}
//3.listen
if(listen(fd,backlog) < 0)
{
perror("listen");
exit(1);
}
//4.accept
/*
int newfd = -1;
newfd = accept(fd,NULL,NULL);
if(newfd < 0)
{
perror("accept");
exit(1);
}
*/
pthread_t tid;
int newfd = -1;
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
while(1)
{
newfd = accept(fd,(struct sockaddr *)&cin,&addrlen);
if(newfd < 0)
{
perror("accept");
exit(1);
}
char ipv4_addr[16];
if(!inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin)))
{
perror("inet_ntop");
exit(1);
}
printf("client : (%s,%d) is connected!\n",ipv4_addr,ntohs(cin.sin_port));
pthread_create(&tid,NULL,client_data_handle,(void *)&newfd);
}
close(fd);
return 0;
}
void* client_data_handle(void *arg)
{
int newfd = *(int *)arg;
char buf[BUFSIZE];
int ret = -1;
printf("handle thread :newfd = %d\n ",newfd);
while(1)
{
do{
bzero(buf,BUFSIZE);
ret = read(newfd,buf,BUFSIZE-1);
}while(ret < 1);
if(ret < 0)
{
exit(1);
}
if(!ret) //ret = 0
{
break;
}
printf("receive data is %s\n",buf);
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
printf("client is exit\n");
break;
}
}
close(newfd);
return NULL;
}
client_thread.c:
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
// ./client 192.168.157.129 5001
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"
int main(int argc,char **argv)
{
int fd = -1;
int port = -1;
port = atoi(argv[2]);
struct sockaddr_in sin;
//1.socket
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd < 0)
{
perror("socket");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(argv[1]);
//2.connect
if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("connect");
exit(1);
}
//3.write
char buf[BUFSIZE];
while(1)
{
bzero(buf,BUFSIZE);
if(fgets(buf,BUFSIZE-1,stdin) == NULL)
{
continue;
}
write(fd,buf,strlen(buf));
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
break;
}
}
return 0;
}
2.TCP多进程并发服务器
service_pro.c:
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/wait.h>
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define backlog 5
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"
void child_data_handle(int signum)
{
if(SIGCHLD == signum)
{
waitpid(-1,NULL,WNOHANG);
}
}
void* client_data_handle(void *arg);
int main()
{
signal(SIGCHLD,child_data_handle);
int fd = -1;
struct sockaddr_in sin;
//1.socket
fd = socket(AF_INET,SOCK_STREAM,0);
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SERV_IP);
// sin.sin_addr.s_addr = inet_addr(SERV_IP_ADDR);
sin.sin_addr.s_addr = INADDR_ANY;
/* if(inet_pton(AF_INET,SERV_IP_ADDR,sin.(void *)&sin_addr.s_addr) != 1)
{
perror("inet_pton");
exit(1);
}
*/
//2.bind
bind(fd,(struct sockaddr *)&sin,sizeof(sin));
//3.listen
listen(fd,backlog);
//4.accept
pid_t pid;
int newfd = -1;
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
while(1)
{
newfd = accept(fd,(struct sockaddr *)&cin,&addrlen);
pid = fork();
if(pid > 0)
{
close(newfd);
}
if(pid == 0)
{
char ipv4_addr[16];
inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin));
printf("client : (%s,%d) is connected!\n",ipv4_addr,ntohs(cin.sin_port));
client_data_handle(&newfd);
close(fd);
}
}
return 0;
}
void* client_data_handle(void *arg)
{
int newfd = *(int *)arg;
char buf[BUFSIZE];
int ret = -1;
printf("child handle porcess :newfd = %d\n ",newfd);
while(1)
{
do{
bzero(buf,BUFSIZE);
ret = read(newfd,buf,BUFSIZE-1);
}while(ret < 1);
if(ret < 0)
{
exit(1);
}
if(!ret) //ret = 0
{
break;
}
printf("receive data is %s\n",buf);
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
printf("client is exit\n");
break;
}
}
close(newfd);
return NULL;
}
client_pro.c不变
额外:TCP的API补充
1.send()
ssize_t send(int sockfd,
const void *buf,
size_t len,
int flags
);
参数:
sockfd:socket函数返回的fd
buf:发送缓冲区首地址
len:发送的字节
flags:发送方式(通常为0),作用和write一样
MSG_DONTWAIT:非阻塞
MSG_OOB:用于TCP类型的带外数据(out of band)
返回值:
成功:实际发送的字节数
失败:-1,并设置errno
2.recv()
ssize_t recv(int sockfd,
void *buf,
size_t len,
int flags
);
flags:一般填0,作用和read一样
特殊的标志:
MSG_DONTWAIT:非阻塞
MSG_OOB:读取带外数据
MSG_PEEK:流
4.UDP编程
receivefrom():阻塞等待客户端数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
sendto():指定服务器的IP地址和端口号,要发送的数据
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
无连接尽力传输,UDP是不可靠传输
实时的音视频传输,DNS域名解析包
service_udp.c :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#define SEVR_PORT 5001
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
int main()
{
//socket
int fd = -1;
fd = socket(AF_INET,SOCK_DGRAM,0);
int b_reuser = 1;
//addr
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuser,sizeof(int));
//bind
struct sockaddr_in sin;
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SEVR_PORT);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
bind(fd,(struct sockaddr*)&sin,sizeof(sin));
//recvfrom
char buf[BUFSIZE];
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
while(1)
{
bzero(buf,BUFSIZE);
recvfrom(fd,buf,BUFSIZE-1,0,(struct sockaddr *)&cin,&addrlen);
char ipv4_addr[16];
inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin));
printf("reveive from (%s,%d),data is %s\n",ipv4_addr,ntohs(cin.sin_port),buf);
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
printf("client (%s,%d) is exit",ipv4_addr,ntohs(cin.sin_port));
}
}
close(fd);
return 0;
}
client_udp.c:
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
// ./client 192.168.157.129 5001
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"
int main(int argc,char **argv)
{
int fd = -1;
int port = -1;
port = atoi(argv[2]);
struct sockaddr_in sin;
//1.socket
fd = socket(AF_INET,SOCK_STREAM,0);
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(argv[1]);
//2.sendto
char buf[BUFSIZE];
while(1)
{
if(fgets(buf,BUFSIZE-1,stdin) == NULL)
{
continue;
}
sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&sin,sizeof(sin));
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
break;
}
}
close(fd);
return 0;
}
原文地址:https://blog.csdn.net/2402_87254779/article/details/143762075
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!