linux多线程服务器
这次的服务器包括了TCP多线程服务器,还包括了UDP的多线程服务器开发,这里主要说明下创建UDP和TCP流程,比如函数的使用方法,我也就简单介绍一下,大家自己查阅资料,当然也可以使用linux下的命令:man来查询,比较方便的。
UDP多线程:支持多客户端连接,当然也支持双方自由发送和接收数据。
TCP多线程:支持多客户端连接,当然也支持双方自由发送和接收数据。
UDP服务器:具体详细我就不一一列举了,大家可以参考我的CSDN博客:https://blog.csdn.net/Travelerwz/article/details/82084468
,相信大家一定遇到这样的文艺,就是要么是服务端收,要么是客户端只能发,这里,我给出一段代码,供大家参考!!
cli:
#include
#include
#include
#include
#include
#include
#define BUFFER 1024
#define PORT 8888
#define ERROR_EXIT(m) \
do \
{\
perror(m);\
exit(1);\
}while(0)
int main()
{
int len = 0;
char buf[BUFFER];
int recv = -1;
int res = -1;
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_port = htons(PORT);
ser.sin_addr.s_addr = htonl(INADDR_ANY);
int socketfd = -1;
//建立socket
socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd
{
ERROR_EXIT("socket");
}
len = sizeof(struct sockaddr);
while(1)
{
printf("waiting---->\n");
char recv_buf[512];
char send_buf[512];
if(NULL != fgets(recv_buf,sizeof(recv_buf),stdin))
{
res = sendto(socketfd,recv_buf,strlen(recv_buf),0,(struct sockaddr*)&ser,sizeof(struct sockaddr));
if(res
ERROR_EXIT("recvfrom");
else
printf("send data:%s\n",recv_buf);
}
res = recvfrom(socketfd,send_buf,strlen(send_buf),0,(struct sockaddr*)&ser,&len);
if(res
{
ERROR_EXIT("recvfrom");
}
else
{
printf("recv from ser :%s\n",send_buf);
}
}
close(socketfd);
return 0;
}
ser:
#include
#include /* See NOTES */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFER 1024
#define PORT 8888
#define ERROR_EXIT(m) \
do \
{\
perror(m);\
exit(1);\
}while(0)
int main()
{
int len = 0;
int res = -1;
int cli_len = 0;
char send_buf[BUFFER];
int recv = -1;
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_port = htons(PORT);
ser.sin_addr.s_addr = htonl(INADDR_ANY);
int socketfd = -1;
//建立socket
socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd
{
ERROR_EXIT("socket");
}
int on = 1;
int ret = -1;
ret = setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
if(ret
{
ERROR_EXIT("setsockopt");
}
len = sizeof(struct sockaddr);
int b = -1;
b = bind(socketfd,(const struct sockaddr*)&ser,len);
if(b
{
ERROR_EXIT("bind");
}
//printf("IP:%s,port %d\n",SERVER_IP,PORT);
cli_len = sizeof(cli);
while(1)
{
printf(" server is waiting:\n");
char recv_send_buf[BUFFER];
char send_buf[BUFFER];
res = recvfrom(socketfd,recv_send_buf,sizeof(recv_send_buf),0,(struct sockaddr*)&cli,&cli_len);
if(res
{
ERROR_EXIT("recvfrom");
}
else
{
printf("from client data:%s\n",recv_send_buf);
}
if(NULL != fgets(send_buf,sizeof(send_buf),stdin))
{
res = sendto(socketfd,send_buf,sizeof(send_buf),0,(struct sockaddr*)&cli,cli_len);
if(res
{
ERROR_EXIT("sendto");
}
else
{
printf("sendto client:%s\n",send_buf);
}
}
}
close(socketfd);
return 0;
}
这个是我们平时创建的单线程的代码,接下来,给大家看一个多线程的代码:
cli:
#include
#include
#include
#include
#include
#include
#include
#define MAX_BUF_SIZE 1024
struct sockaddr_in srvaddr,clientaddr;
int sockfd,port,addrlen;
char s_msg[MAX_BUF_SIZE];
char receive[MAX_BUF_SIZE];
char bye[MAX_BUF_SIZE] = "bye\n";
void send_msg(void);//Ï̺߳¯Êý£¬·¢ÏûÏ¢
int main(int argc, char *argv[])
{
pthread_t pt_send = 0;
int ret;
//bye="bye\n";
if (argc!=3) {
printf("Usage:%s server_ip server_port\n", argv[0]);
return -1;
}
//convert port number
if ((port=atoi(argv[2]))
printf("port error\n");
return -1;
}
//create client udp socket
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1){
printf("Socket create error\n");
return -1;
}
//assign server's sock address
addrlen=sizeof(struct sockaddr_in);
memset(&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family=AF_INET;
srvaddr.sin_port=htons(port);
//convert IP address
if(inet_aton(argv[1],&srvaddr.sin_addr)
printf("IP error\n");
close(sockfd);
return -1;
}
printf("input bye to end CLIENT\n");
ret = pthread_create (&pt_send, NULL, (void *)send_msg, NULL);
if (ret != 0)
printf("pthread send_msg creat error\n");
while(1)
{
memset(receive,0, MAX_BUF_SIZE);
//receive message from remote server and print it
recvfrom(sockfd, receive, MAX_BUF_SIZE, MSG_DONTWAIT, (struct sockaddr *)(&clientaddr), &addrlen);
if (receive[0] != '\0' )
fprintf(stdout, "Receive message from server: %s", receive);
if (strcmp(receive,bye) == 0)
{
//printf("end session\n");
break;
}
}
//close socket
pthread_join (pt_send, NULL);
close(sockfd);
return 0;
}
void send_msg(void)
{
while(1)
{
memset(s_msg, 0, MAX_BUF_SIZE);
//get message from standard input
fgets(s_msg, MAX_BUF_SIZE, stdin);
//send message to remote server and print it
sendto(sockfd,s_msg,strlen(s_msg),MSG_DONTWAIT,(struct sockaddr *)(&srvaddr),addrlen);
printf("Client input message: %s", s_msg);
if (strcmp(s_msg, bye) == 0)
{
printf("end session\n");
break;
}
}
}
ser:
#include
#include
#include
#include
#include
#include
#define MAX_MSG_SIZE 1024
#define SERVER_PORT 3000
char s_msg[MAX_MSG_SIZE];//发消息
char receive[MAX_MSG_SIZE];//收消息
char bye[MAX_MSG_SIZE]="bye\n";
struct sockaddr_in srvaddr,clientaddr;
int sockfd,addrlen;
void send_msg(void);//线程函数,发消息
int main()
{
pthread_t pt_send = 0;
int ret;
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)//套接字描述符
{
printf("Socket create error\n");
return -1;
}
//assign server's sock address
memset(&srvaddr, 0, sizeof(srvaddr));
addrlen=sizeof(srvaddr);
srvaddr.sin_family=AF_INET;
srvaddr.sin_port=htons(SERVER_PORT);
if(inet_aton("127.0.0.1",&srvaddr.sin_addr)==-1)
{
printf("addr convert error\n");
close(sockfd);
return -1;
}
//srvaddr.sin_addr.s_addr=htonl(INADDR_ANY);
//bind IP address and port
if(bind(sockfd,(struct sockaddr *)&srvaddr,addrlen)==-1)
{
printf("bind error\n");
close(sockfd);
return -1;
}
printf("input bye to end SERVER\n");
ret = pthread_create (&pt_send, NULL, (void *)send_msg, NULL);
if (ret != 0)
printf("pthread send_msg creat error\n");
while(1)
{
memset(receive, 0, MAX_MSG_SIZE);
recvfrom(sockfd, receive, MAX_MSG_SIZE, 0, (struct sockaddr *)(&clientaddr), &addrlen);//非阻塞
if (receive[0] != '\0' )
fprintf(stdout, "Receive message from client: %s", receive);
if (strcmp(receive,bye) == 0)
break;
}
//while收消息,显示到标准输出,发消息,从标准如入写
//close socket
pthread_join (pt_send, NULL);
close(sockfd);
return 0;
}
void send_msg(void)
{
while(1)
{
memset(s_msg, 0, MAX_MSG_SIZE);
//get message from standard input
fgets(s_msg, MAX_MSG_SIZE, stdin);
//send message to client
sendto(sockfd,s_msg,strlen(s_msg),0,(struct sockaddr *)(&clientaddr),addrlen);
printf("Server input message: %s", s_msg);
if (strcmp(s_msg, bye) == 0)
{
printf("end session\n");
break;
}
}
}
接下来,我们看看TCP的代码,由于代码很容易理解,我就不一一解释了,不懂得可以私聊我。
cli:
#include
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define MAX_NUM 128
#define ERROR(m) \
do \
{ \
perror(m); \
exit(0); \
}while(0)
int Socket()
{
int fd = 0;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd
{
ERROR("socket");
}
return fd;
}
int main()
{
int sockfd = -1;
int res = -1;
char recvbuf[MAX_NUM];
char sendbuf[MAX_NUM];
int num = 10;
pthread_t tid;
struct sockaddr_in cliaddr;
memset(&cliaddr,0,sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
////IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_port = htons(PORT);
//创建套接字
sockfd = Socket();
int len = sizeof(cliaddr);
res = connect(sockfd,(struct sockaddr*)&cliaddr,len);
if(res
{
ERROR("connect");
}
printf("--------\n");
void* Write(void *arg)
{
while(1)
{
memset(sendbuf,0,MAX_NUM);
fgets(sendbuf,MAX_NUM,stdin);
res = send(sockfd,sendbuf,MAX_NUM,MSG_DONTWAIT);
printf("send:%s\n",sendbuf);
}
}
pthread_create(&tid,NULL,Write,NULL);
while(1)
{
res = recv(sockfd,recvbuf,MAX_NUM,MSG_DONTWAIT);
if(res > 0)
{
printf("recv:%s\n",recvbuf);
}
}
pthread_join(tid,NULL);
close(sockfd);
return 0;
}
ser:
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define MAX_NUM 128
#define ERROR(m) \
do \
{ \
perror(m); \
exit(0); \
}while(0)
char recvbuf[MAX_NUM];
char sendbuf[MAX_NUM];
int res = -1;
int sockfd = -1;
int connect_fd = -1;
int Socket()
{
int fd = 0;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd
{
ERROR("socket");
}
return fd;
}
void Listen(int fd,int num)
{
int res = -1;
res = listen(fd,num);
if(res
{
ERROR("listen");
}
return ;
}
int main()
{
pthread_t tid,tid2;
int num = 10;
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
////IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
seraddr.sin_port = htons(PORT);
//创建套接字
sockfd = Socket();
//端口复用
int opt = 1;
if(setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, (const void *) &opt, sizeof(opt)))
{
ERROR("setsockopt");
}
//绑定
if(bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr))
{
ERROR("bind");
}
//监听
Listen(sockfd,num);
//读
void *Recv(void *arg)
{
while(1)
{
memset(recvbuf, 0, MAX_NUM);
res = recv(connect_fd,recvbuf,MAX_NUM,MSG_DONTWAIT);
if(res >= 0)
{
printf("recv:%s\n",recvbuf);
}
}
}
//写
void *Write(void *arg)
{
while(1)
{
memset(sendbuf,0,MAX_NUM);
fgets(sendbuf,MAX_NUM,stdin);
res = send(connect_fd,sendbuf,MAX_NUM,0);
printf("send:%s\n",sendbuf);
}
}
//等待客户端连接
printf("waiting client coming:\n");
int len = sizeof(seraddr);
while(1)
{
connect_fd = accept(sockfd,(struct sockaddr*)&seraddr,&len);
if(connect_fd
{
ERROR("accept");
}
printf("--------\n");
//创建线程
pthread_create(&tid,NULL,Write,NULL);
pthread_create(&tid2,NULL,Recv,NULL);
pthread_join(tid,NULL);
pthread_join(tid2,NULL);
}
close(connect_fd);
//pthread_create(&tid2,NULL,Write,NULL);
pthread_join(tid,NULL);
//pthread_detach(tid2);
close(sockfd);
return 0;
}
这就是创建TCP和UDP多线程服务器的代码,内容比较简单,具体流程可以参考我的博客,https://blog.csdn.net/Travelerwz/article/details/82084468,不懂得,大家可以私信我,谢谢!!
识别二维码,关注我们
CPP后台服务器开发
linux|shell|C/C++|python
领取专属 10元无门槛券
私享最新 技术干货