linux下socket实现多个客户端与服务器的通信

阅读: 评论:0

linux下socket实现多个客户端与服务器的通信

linux下socket实现多个客户端与服务器的通信

学习完《UNIX环境高级编程》套接字一章的内容之后,自己实现了单个客户端与服务器的通信程序,后面想想要是多个客户端如何与服务器通信呢?这就有了这篇文章。

这里采用的是用多线程实现多客户端与服务器的通信,多线程的思路参考了Linux C利用Socket套接字进行服务器与多个客户端进行通讯,在此感谢原文章作者。


服务器端程序:

#include<stdio.h>#include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h>#include <unistd.h>#include <arpa/inet.h>#include <fcntl.h>#include <pthread.h>#define BUFLEN 128#define QLEN   10#define DATALEN 200#define SERVPORT 48800#define HOST_NAME_MAX 256
#define IPLEN  16//store accept id of client connect to serverint acceptfd[QLEN];
//number of client connect to server int acceptnum = 0;//information from main thread to created thread 
struct threadinfo
{int 	clfd;char	ipaddr[IPLEN];int 	port;
};void sys_err(char *errinfo){if(NULL == errinfo){return;}perror("errinfo");exit(0);}int initsrver(int type, const struct sockaddr *addr, socklen_t alen, int qlen){int fd;int err = 0;int reuse = -1;if((fd = socket(addr->sa_family, type, 0)) < 0){return -1;}//set socket optionif(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0)goto errout;if(bind(fd, addr, alen) < 0)goto errout;if(type == SOCK_STREAM || type == SOCK_SEQPACKET){//listenif(listen(fd, qlen) < 0)goto errout;}return fd;errout:err = errno;close(fd);errno = err;return -1;}void *recvmessage(void *arg){char buf[BUFLEN];char recvtitle[DATALEN] = "receive from ";int n;struct threadinfo *ti = arg;memset(buf, 0, BUFLEN);sprintf(recvtitle, "%s%s:%d ", recvtitle, ti->ipaddr, ti->port);while((n = recv(ti->clfd, buf, BUFLEN, 0)) > 0){write(STDOUT_FILENO, recvtitle, strlen(recvtitle));write(STDOUT_FILENO, buf, n);memset(buf, 0, BUFLEN);}if(n < 0)printf("recv errorn");}void *acceptThread(void *sockfd){int clfd;const char *addr;char buf[BUFLEN];int n;char abuf[INET_ADDRSTRLEN];struct sockaddr_in clientsockaddr;int clientlen;int err;pthread_t recvtid;struct threadinfo ti;clientlen = sizeof(clientsockaddr);//always accept new client to accept a lot of client while(1){if((clfd = accept(*(int *)sockfd, (struct sockaddr *)&clientsockaddr, &clientlen)) < 0)sys_err("accept error");printf("%s:%d login in to servern", inet_ntoa(clientsockaddr.sin_addr), clientsockaddr.sin_port);//when accept client, store it's accept idacceptfd[acceptnum++] = clfd;//create thread to receive message of every clientti.clfd = clfd;strcpy(ti.ipaddr, inet_ntoa(clientsockaddr.sin_addr));ti.port = clientsockaddr.sin_port;if((err = pthread_create(&recvtid, NULL, recvmessage, &ti)) != 0)sys_err("pthread_create recvmessage error");}}int communication(int sockfd){int 	clfd;pid_t	pid;char	buf[BUFLEN];int 	fd;int 	err;pthread_t acpttid;int 	i;memset(buf, 0, BUFLEN);//create thread to accept client, always accept to accept a lot of clientif((err = pthread_create(&acpttid, NULL, acceptThread, &sockfd)) != 0)sys_err("pthread_create acceptThread error");//send message to client, but only send the same mesage to all connected client nowmemset(buf, 0, BUFLEN);while(1){if(fgets(buf, BUFLEN, stdin) != NULL){//print the num of accept client connect to serverprintf("acceptnum: %dn", acceptnum);for (i = 0; i < acceptnum; ++i){send(acceptfd[i], buf, strlen(buf), 0);}memset(buf, 0, BUFLEN);}}close(clfd);}int main(int argc, char *argv[]){struct sockaddr_in serversockaddr, clientsockaddr;int 	sockfd, clientfd;int err, n;if(argc != 1){printf("usage: %sn", argv[0]);exit(0);}serversockaddr.sin_family = AF_INET;serversockaddr.sin_port = htons(SERVPORT);serversockaddr.sin_addr.s_addr = INADDR_ANY;bzero(&(serversockaddr.sin_zero), 8);if((sockfd = initsrver(SOCK_STREAM, (struct sockaddr *)&serversockaddr, sizeof(struct sockaddr), QLEN)) > 0){//start communicationcommunication(sockfd);exit(0);}exit(0);}


客户端程序:

#include<stdio.h>#include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h>#include <unistd.h>#include <arpa/inet.h>#include <fcntl.h>#include <pthread.h>#define SERVPORT 48800#define MAXSLEEP 128#define BUFLEN 128#define DATALEN 200int connect_retry(int domain, int type, int protocol, const struct sockaddr *addr){int numsec, fd;//try to connect with exponential backofffor(numsec = 1; numsec <= MAXSLEEP; numsec <<= 1){if((fd = socket(domain, type, protocol)) < 0)return -1;if(connect(fd, addr, sizeof(struct sockaddr)) == 0){return fd;}close(fd);//delay before trying againif(numsec <= MAXSLEEP/2)sleep(numsec);}return -1;}void *sendmessage(void *arg){int sockfd;char	buf[BUFLEN];sockfd = *(int *)arg;memset(buf, 0, BUFLEN);while(fgets(buf, BUFLEN, stdin) != NULL){send(sockfd, buf, strlen(buf), 0);memset(buf, 0, BUFLEN);}}void communication(int sockfd){int n;pid_t pid;char buf[BUFLEN];char *recvtitle = "received from server: ";int fd;int err;pthread_t tid;memset(buf, 0, BUFLEN);//create thread to send messageif(err = pthread_create(&tid, NULL, sendmessage, &sockfd)){printf("pthread_create errorn");exit(0);}//receive messagewhile(1){while((n = recv(sockfd, buf, BUFLEN, 0)) > 0){write(STDOUT_FILENO, recvtitle, strlen(recvtitle));write(STDOUT_FILENO, buf, n);memset(buf, 0, BUFLEN);}if(n < 0)printf("recv errorn");}}int main(int argc, char *argv[]){int sockfd, err;struct sockaddr_in serversockaddr;const char	*addr;char abuf[INET_ADDRSTRLEN];struct hostent *host;if(argc != 2){printf("usage: %s hostnamen", argv[0]);exit(0);}if((host = gethostbyname(argv[1])) == NULL){perror("gethostbyname");exit(0);}serversockaddr.sin_family = AF_INET;serversockaddr.sin_port = htons(SERVPORT);serversockaddr.sin_addr = *((struct in_addr *)host->h_addr);bzero(&(serversockaddr.sin_zero), 0);if((sockfd = connect_retry(serversockaddr.sin_family, SOCK_STREAM, 0, (struct sockaddr *)&serversockaddr)) < 0){err = errno;}else{communication(sockfd);exit(0);}printf("can't connect to %sn", argv[1]);exit(0);}



本文发布于:2024-02-04 11:58:48,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170706668255358.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:多个   客户端   通信   服务器   linux
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23