大多数TCP服务器是并发的,他们为每个待处理的客户连接调用fork派生出一个子进程。
下面是一个很初级的使用子进程实现并发的例子。
1. server.cpp:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h> //toupper()
#include <errno.h>
void string2Upper(char* data, int len)
{
if (NULL == data || len <= 0)
return;
for(int i = 0; i < len; i++)
data[i] = toupper(data[i]);
}
int main(int argc, char *argv[])
{
int srvfd, connfd;
struct sockaddr_in srvaddr;
struct sockaddr_in cltaddr;
//argv[1]作为port
if (argc != 2)
{
printf("Usage:%s port\n", argv[0]);
return -1;
}
int port = atoi(argv[1]);
//create server socket
srvfd = socket(AF_INET, SOCK_STREAM, 0);
//set address
bzero(&srvaddr, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
//srvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
srvaddr.sin_addr.s_addr = htons(INADDR_ANY);
srvaddr.sin_port = htons(port);
bind(srvfd, (struct sockaddr*)&srvaddr, sizeof(srvaddr));
listen(srvfd, 5);
while(1)
{
printf("server is waiting...");
socklen_t cltlen = sizeof(cltaddr);
connfd = accept(srvfd, (struct sockaddr*)&cltaddr, &cltlen);
if (-1 == connfd)
{
if(errno == EINTR)
continue;
else
{
perror("can not accept client connect.\n");
close(srvfd);
return -1;
}
}
pid_t pid = fork();
if (0 == pid)
{
close(srvfd);
int readlen;
char buf[1024];
while(1)
{
memset(buf, 0, 1024);
readlen = read(connfd, buf, sizeof(buf));
if (readlen == -1)
{
printf("read error, exit.\n");
break;
}
if (readlen >0 && buf[0] == '@')
break;
buf[readlen] = '\0';
printf("read from client: %s\n", buf);
string2Upper(buf, readlen);
write(connfd, buf, readlen);
}
close(connfd);
return 0;
}
close(connfd);
}
return 0;
}
2. client.cpp
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int cltfd;
socklen_t srvlen, cltlen;
struct sockaddr_in srvaddr;
struct sockaddr_in cltaddr;
int ret;
char buf[1024];
//argv[1]作为port
if (argc != 3)
{
printf("Usage:%s port\n", argv[0]);
return -1;
}
int port = atoi(argv[2]);
if ((cltfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("can not create client socket");
return -1;
}
bzero(&srvaddr, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_addr.s_addr = inet_addr(argv[1]);
srvaddr.sin_port = htons(port);
srvlen = sizeof(srvaddr);
if (connect(cltfd, (struct sockaddr*)&srvaddr, srvlen) < 0)
{
printf("connect error.\n");
return -1;
}
memset(buf, 0, 1024);
while(1)
{
memset(buf, 0, 1024);
write(STDOUT_FILENO, "input message:", 14);
int len = read(STDIN_FILENO, buf, 1024);
if (len > 0)
write(cltfd, buf, len);
len = read(cltfd, buf, len);
if (len > 0)
printf("Message from server : %s\n", buf);
if(buf[0] == '@')
break;
}
close(cltfd);
return 0;
}