服务器端代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 1234
#define MAXSIZE 1024
struct 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='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
#include
#include
#include
#include
#include
#include
#include
#define PORT 1234
#define MAXSIZE 1024
static 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 \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退出时,结果却不打印保存的信息。这是为什么?这就是非线程安全的问题。