linux下socket实现多个客户端与服务器的通信
2016-09-25 13:30
423 查看
学习完《UNIX环境高级编程》套接字一章的内容之后,自己实现了单个客户端与服务器的通信程序,后面想想要是多个客户端如何与服务器通信呢?这就有了这篇文章。
这里采用的是用多线程实现多客户端与服务器的通信,多线程的思路参考了Linux
C利用Socket套接字进行服务器与多个客户端进行通讯,在此感谢原文章作者。
服务器端程序:
客户端程序:
这里采用的是用多线程实现多客户端与服务器的通信,多线程的思路参考了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 server int 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 option if(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) { //listen if(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 error\n"); } 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 server\n", inet_ntoa(clientsockaddr.sin_addr), clientsockaddr.sin_port); //when accept client, store it's accept id acceptfd[acceptnum++] = clfd; //create thread to receive message of every client ti.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 client if((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 now memset(buf, 0, BUFLEN); while(1) { if(fgets(buf, BUFLEN, stdin) != NULL) { //print the num of accept client connect to server printf("acceptnum: %d\n", 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: %s\n", 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 communication communication(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 200 int connect_retry(int domain, int type, int protocol, const struct sockaddr *addr) { int numsec, fd; //try to connect with exponential backoff for(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 again if(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 message if(err = pthread_create(&tid, NULL, sendmessage, &sockfd)) { printf("pthread_create error\n"); exit(0); } //receive message while(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 error\n"); } } 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 hostname\n", 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 %s\n", argv[1]); exit(0); }
相关文章推荐
- Linux下网络socket编程——实现服务器(select)与多个客户端通信
- Linux下通过socket通信实现客户端向服务器发送文件
- linux下socket编程 select实现非阻塞模式多台客户端与服务器通信
- Linux socket编程入门及客户端服务器端通信实现 – 提高篇:TCP连接过程分析
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- Java 利用套接字Socket实现简单的服务器与客户端通信
- linux socket实现网络聊天室(一):服务器和客户端对话
- Android客户端与PC服务器实现Socket通信(wifi)
- Linux 网络编程实现TCP协议下的服务器客户端通信
- Java 利用套接字Socket实现简单的服务器与客户端通信
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- Android简单实现Socket通信,客户端连接服务器后,服务器向客户端发送文字数据
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- java 通过 socket 实现 服务器和客户端的通信 TCP
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Linux下socket编程实现客户机服务器通信的例子
- python socket 实现服务器/客户端通信