求修改c语言 多线程server 代码!!
最近写了一个Linux环境下的C语言代码,目的是用线程实现并行四则运算server。期待的效果是多个client把运算参数和运算符号传给server,server接收多个运算请求并运用线程分别计算,把结果返回给相应的client。 但是实际执行时从client1先发出运算请求,然后client2发出运算请求,server可以接收两个请求,但server算出client1的结果并返回给client1后就跳出循环,关闭socket了,返回给client2结果永远是0。想问问各位大神代码错误出在哪?应该怎么修改使之实现并行运算并正确返回结果。server代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#define SUCCESS 0
#define ERROR 1
#define SERVER_PORT 1600
#define MAX_MSG 256
int server; /* listening socket descriptor */
/**
* cleanup() is called to kill the thread upon SIGINT.
**/
void cleanup()
{
close(server);
pthread_exit(NULL);
return;
} /* cleanup() */
/**
* Thread handler for incoming connections...
**/
void handler(void * paramsd) {
struct sockaddr_in cliAddr;
int client_local; /* keep a local copy of the client's socket descriptor */
int addr_len; /* used to store length (size) of sockaddr_in */
int ch[4];
client_local = *((int *)paramsd); /* store client socket descriptor */
addr_len = sizeof(cliAddr); /* store value of size of sockaddr_in */
/* get clients name and store in cliAddr */
getpeername(client_local, (struct sockaddr*)&cliAddr, &addr_len);
/* reset line */
read(client_local,ch,sizeof(ch)); /* now read lines from the client socket */
while(1) /* loop - read from socket */
{
if (ch[1]==1){
ch[3]=ch[0]+ch[2];
}else if(ch[1]==2){
ch[3]=ch[0]-ch[2];
}else if(ch[1]==3){
ch[3]=ch[0]*ch[2];
}else if(ch[1]==4){
ch[3]=ch[0]/ch[2];
}
send(client_local, ch,sizeof(ch),0);
}
close(client_local);
return;
} /* handler() */
/* main function */
int main (int argc, char *argv[])
{
int client; /* client socket descriptor */
int addr_len; /* used to store length (size) of sockaddr_in */
pthread_t thread; /* thread variable */
struct sockaddr_in cliAddr; /* socket address for client */
struct sockaddr_in servAddr; /* socket address for server */
signal(SIGINT, cleanup); /* now handle SIGTERM and SIGINT */
signal(SIGTERM, cleanup);
/* now create the server socket
make it an IPV4 socket (PF_INET) and stream socket (TCP)
and 0 to select default protocol type */
server = socket(PF_INET, SOCK_STREAM, 0);
if (server < 0) {
perror("cannot open socket ");
return ERROR;
}
/* now fill in values of the server sockaddr_in struct
s_addr and sin_port are in Network Byte Order (Big Endian)
Since Intel CPUs use Host Byte Order (Little Endian), conversion
is necessary (e.g. htons(), and htonl() */
servAddr.sin_family = AF_INET; /* again ipv4 */
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* local address */
servAddr.sin_port = htons(SERVER_PORT);
memset(servAddr.sin_zero, 0, 8);
/* now bind server port
associate socket (server) with IP address:port (servAddr) */
if (bind(server, (struct sockaddr *) &servAddr, sizeof(struct sockaddr)) < 0) {
perror("cannot bind port ");
return ERROR;
}
/* wait for connection from client with a pending queue of size 5 */
listen(server, 5);
while(1) /* infinite loop */
{
int ch[4];
printf("%s: waiting for data on port TCP %u\n", argv[0], SERVER_PORT);
addr_len = sizeof(cliAddr);
/* new socket for client connection
accept() will block until a connection is present
accept will return a NEW socket for the incoming connection
server socket will continue listening
store client address in cliAddr */
client = accept(server, (struct sockaddr *) &cliAddr, &addr_len);
if (client < 0) {
perror("cannot accept connection ");
break;
}
pthread_create(&thread, 0, (void*)&handler, (void*) &client);
} /* while (1) */
close(server);
exit(0);
} /* main() */
client代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close */
#include <string.h>
#include <stdlib.h>
#define SERVER_PORT 1600
#define MAX_MSG 256
/* main() */
int main (int argc, char *argv[]) {
int client; /* client socket */
int rc;
struct sockaddr_in local_addr, serv_addr;
struct hostent * host;
int ch[4];
if(argc < 2) {
printf("usage: %s <server>\n",argv[0]);
exit(-1);
}
/* get host address from specified server name */
host = gethostbyname(argv[1]);
if (host == NULL)
{
printf("%s: unknown host '%s'\n",argv[0],argv[1]);
exit(-1);
}
/* now fill in sockaddr_in for remote address */
serv_addr.sin_family = host->h_addrtype;
/* get first address in host, copy to serv_addr */
memcpy((char *) &serv_addr.sin_addr.s_addr, host->h_addr_list[0], host->h_length);
serv_addr.sin_port = htons(SERVER_PORT);
memset(serv_addr.sin_zero, 0, 8);
/* create local stream socket */
client = socket(PF_INET, SOCK_STREAM, 0);
if (client < 0) {
perror("cannot open socket ");
exit(-1);
}
/* bind local socket to any port number */
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
local_addr.sin_port = htons(0);
memset(local_addr.sin_zero, 0, 8);
rc = bind(client, (struct sockaddr *) &local_addr, sizeof(local_addr));
if (rc < 0)
{
printf("%s: cannot bind port TCP %u\n",argv[0],SERVER_PORT);
perror("error ");
exit(1);
}
/* connect to server */
rc = connect(client, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (rc < 0)
{
perror("cannot connect ");
exit(1);
}
printf("A=");
scanf("%d",&ch[0]);
printf("sign=(1=+,2=-,3=*,4=/)");
scanf("%d",&ch[1]);
printf("B=");
scanf("%d",&ch[2]);
rc = send(client,ch,sizeof(ch),0);
if (rc < 0)
{
perror("cannot send data ");
close(client);
exit(-1);
}
read(client,ch,sizeof(ch));
printf("answer= %d \n",ch[3]);
close(client);
return 0;
} /* main() */