上一节简单如何通过Socket创建一个连接,然后进行通信。只是每个人只能说一句话。而且还是必须说完才会接收到信息,总之是很不方便的事情。所以这一小节我们将对上一次的程序进行修改,修改成每个人可以多说话,主要是通过Linux下多进程fork实现的。
一对一,server和client是每个人都可以多说几句话
由于控制台度数据的函数fgets是阻塞函数,要每个人都可以多说话,这里我使用的是读取和发送都在不同的进程里面,使之互相没有影响。
fork函数
#include <unistd.h>
pid_t fork(void); //返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1
client.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h> //for gethostbyname
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define MAX_BUF 4096
#define SERVER_PORT 12138 int main(int argc,char *argv[])
{
int sockfd;//socket
char sendBuf[MAX_BUF],recvBuf[MAX_BUF];
int sendSize,recvSize;//用于记录记录发送和接收到数据的大小
struct hostent * host;
struct sockaddr_in servAddr;
char username[];
char * p;
int pid; if(argc != )
{
perror("use: ./client [hostname] [username]");
exit(-);
}
p=username;
strcpy(p,argv[]);
printf("username:%s\n",username);
host=gethostbyname(argv[]);
if(host==NULL)
{
perror("fail to get host by name.");
exit(-);
}
printf("Success to get host by name ...\n"); //创建socket
if((sockfd=socket(AF_INET,SOCK_STREAM,))==-)
{
perror("fail to establish a socket");
exit();
}
printf("Success to establish a socket...\n"); /*init sockaddr_in*/
servAddr.sin_family=AF_INET;
servAddr.sin_port=htons(SERVER_PORT);
servAddr.sin_addr=*((struct in_addr *)host->h_addr);
bzero(&(servAddr.sin_zero),); /*connect the socket*/
if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-)
{
perror("fail to connect the socket");
exit();
}
printf("Success to connect the socket...\n"); //send-recv 一些返回指没有判断,具体可以看server.c
if((pid=fork())<)
{
perror("fork error\n");
}
else if(pid>)/*child*/
{
while()
{
fgets(sendBuf,MAX_BUF,stdin);
send(sockfd,sendBuf,strlen(sendBuf),);
memset(sendBuf,,sizeof(sendBuf));
}
}
else
{
while()
{
recv(sockfd,recvBuf,MAX_BUF,);
printf("Server:%s\n",recvBuf);
memset(recvBuf,,sizeof(recvBuf));
}
} return ;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define SERVER_PORT 12138
#define BACKLOG 20
#define MAX_CON_NO 10
#define MAX_DATA_SIZE 4096 int main(int argc,char *argv[])
{
struct sockaddr_in serverSockaddr,clientSockaddr;
char sendBuf[MAX_DATA_SIZE],recvBuf[MAX_DATA_SIZE];
int sendSize,recvSize;
int sockfd,clientfd;
int on=;
int sinSize=;
char username[];
int pid; if(argc != )
{
printf("usage: ./server [username]\n");
exit();
}
strcpy(username,argv[]);
printf("username:%s\n",username); /*establish a socket*/
if((sockfd = socket(AF_INET,SOCK_STREAM,))==-)
{
perror("fail to establish a socket");
exit();
}
printf("Success to establish a socket...\n"); /*init sockaddr_in*/
serverSockaddr.sin_family=AF_INET;
serverSockaddr.sin_port=htons(SERVER_PORT);
serverSockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&(serverSockaddr.sin_zero),); setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); /*bind socket*/
if(bind(sockfd,(struct sockaddr *)&serverSockaddr,sizeof(struct sockaddr))==-)
{
perror("fail to bind");
exit();
}
printf("Success to bind the socket...\n"); /*listen on the socket*/
if(listen(sockfd,BACKLOG)==-)
{
perror("fail to listen");
exit();
} /*accept a client's request*/ //这里的sinSize还没有处理,具体看下一节
if((clientfd=accept(sockfd,(struct sockaddr *)&clientSockaddr, &sinSize))==-)
{
perror("fail to accept");
exit();
}
printf("Success to accpet a connection request...\n");
printf(" %s join in!\n",inet_ntoa(clientSockaddr.sin_addr)); if((pid=fork())<)
{
perror("fork error\n");
}
else if(pid>)/*child*/
{
/*send datas to client*/
while()
{
fgets(sendBuf,MAX_DATA_SIZE,stdin);
if((sendSize=send(clientfd,sendBuf,strlen(sendBuf),))!=strlen(sendBuf))
{
perror("fail to send datas");
exit();
}
printf("Success to send datas\n");
memset(sendBuf,,MAX_DATA_SIZE);
}
}
else
{
while()
{
/*receive datas from client*/
if((recvSize=recv(clientfd,recvBuf,MAX_DATA_SIZE,))==-)
{
perror("fail to receive datas");
exit();
}
printf("Client:%s\n",recvBuf);
memset(recvBuf,,MAX_DATA_SIZE);
} } return ;
}