linux网络编程多进程并发服务器

来源:互联网 发布:js sort函数 编辑:程序博客网 时间:2024/04/28 23:54

服务器端代码

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <pthread.h>#define PORT 1234#define MAXSIZE1024struct ARG{int connfd;struct sockaddr_in clientAddr;};void savedata(char *recvbuf, int len, char *cli_data){static int index = 0;int i = 0;while (i < len-1){cli_data[index++] = recvbuf[i];i++;}cli_data[index] = '\0';}static int clientProcess(int connfd, struct sockaddr_in clientSock){int num = 0;int i = 0;char recvBuf[MAXSIZE];char sendBuf[MAXSIZE];char clientName[MAXSIZE];char cli_data[MAXSIZE];struct timeval val;fd_set fd;int ret;val.tv_sec = 0;val.tv_usec = 0;num = recv(connfd, clientName, MAXSIZE, 0);if (num < 0){printf("recv clientName message from client!\n");return -1;}clientName[strlen(clientName)-1] = '\0';printf("You got's a connection from %s, client name is %s\n",inet_ntoa(clientSock.sin_addr), clientName);while (1){FD_ZERO(&fd);FD_SET(connfd, &fd);ret = select(FD_SETSIZE, &fd, NULL, NULL, &val);num = recv(connfd, recvBuf, MAXSIZE, 0);if (num == 0){printf("Client(%s) closed connection\nUser's data:%s\n",clientName, cli_data);close(connfd);return -1;}recvBuf[strlen(recvBuf)-1] = '\0';printf("received client (%s) message :%s\n", clientName, recvBuf);//保存接收到的信息savedata(recvBuf, num, cli_data);//将接收到的客户端数据加密返回给客户端for (i=0; i<num-1; i++) {if ((recvBuf[i]>='a' && recvBuf[i]<='z') || (recvBuf[i]>='A' && recvBuf[i]<='Z')){recvBuf[i] = recvBuf[i] + 3;if ((recvBuf[i]>'Z' && recvBuf[i]<'Z'+3) || (recvBuf[i]>'z')){recvBuf[i] = recvBuf[i] -26;}}sendBuf[i] = recvBuf[i];}sendBuf[num-1] = '\0';send(connfd, sendBuf, MAXSIZE, 0);memset(sendBuf, 0, MAXSIZE);memset(recvBuf, 0, MAXSIZE);}close(connfd);return 1;}void *funThread(void *arg){struct ARG *info;info = (struct ARG *)arg;clientProcess(info->connfd, info->clientAddr);free(arg);arg = NULL;pthread_detach(pthread_self());pthread_exit(NULL);}int main(int argc, char **argv){int listenfd, connfd;pthread_t pid_t;struct ARG *arg;struct sockaddr_in serveraddr;struct sockaddr_in clientaddr;socklen_t len;listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd < 0){printf("Creating socket failed!\n");return -1;}int opt = SO_REUSEADDR;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));bzero(&serveraddr, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(PORT);serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){printf("bind fails!\n");return -1;}if (listen(listenfd, 5) < 0){printf("listen fails!\n");return -1;}len = sizeof(clientaddr);for (;;){connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &len);if (connfd < 0){printf("accept fails!\n");return -1;}arg = (struct ARG *)malloc(sizeof(struct ARG));if (arg == NULL){printf("malloc memory fails!\n");return -1;}memset(arg, 0, sizeof(struct ARG));arg->connfd = connfd;memcpy((void *)&arg->clientAddr, &clientaddr, sizeof(clientaddr));//处理客户端信息if (pthread_create(&pid_t, NULL, funThread, (void *)arg) < 0){printf("Create thread fails!\n");return -1;}}close(listenfd);}

客户端代码:

#include <string.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#define PORT1234#define MAXSIZE 1024static int clientProcess(FILE *fp, int connfd){char readLine[MAXSIZE];char recvLine[MAXSIZE];int num;printf("connect to server success!\n");printf("Input client's name:");if (fgets(readLine, MAXSIZE, fp) == NULL){printf("fgets fails!\n");return -1;}send(connfd, readLine, MAXSIZE, 0);while (fgets(readLine, MAXSIZE, fp) != NULL){if (strncmp(readLine, "quit", strlen("quit")) == 0){fflush(stdin);exit(-1);}send(connfd, readLine, strlen(readLine), 0);num = recv(connfd, recvLine, MAXSIZE, 0);if (num < 0){printf("received fails!\n");return -1;}recvLine[num-1] = '\0';printf("Server message:%s\n", recvLine);}return 1;}int main(int argc, char **argv){int sockfd;struct sockaddr_in serverSock;struct hostent *he;if (argc != 2){printf("Usage: %s <IP Address>\n", argv[0]);return -1;}he = gethostbyname(argv[1]);if (he == NULL){printf("gethostbyname fails!\n");return -1;}sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){printf("Create socket fails!\n");return -1;}bzero(&serverSock, sizeof serverSock);serverSock.sin_family = AF_INET;serverSock.sin_port = htons(PORT);serverSock.sin_addr = *((struct in_addr *)he->h_addr);if (connect(sockfd, (struct sockaddr *)&serverSock, sizeof serverSock) < 0){printf("connect fails!\n");return -1;}clientProcess(stdin, sockfd);close(sockfd);return 1;}
编译运行。

首先运行服务器程序,然后打开两个客户端终端并连接上服务器程序。如下图所示:

服务器运行情况:

客户端1运行情况:

客户端2运行情况:


仔细看服务端运行情况就能看到问题,当客户端1退出后,执行

savedata(recvBuf, num, cli_data);
的信息能够打印出来,当客户端2退出时,结果却不打印保存的信息。这是为什么?这就是非线程安全的问题。