功能:
实现两个主机之间的局域网聊天
实现关键:
如何同时处理套接字的输入和标准输入 --- select函数
客户端的程序
#include "unp.h"
void cli_echo(FILE *fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char buf[1000];
int n;
stdineof=0;
FD_ZERO(&rset);
for(;;){
if(stdineof==0)
FD_SET(fileno(fp),&rset);
FD_SET(sockfd,&rset);
maxfdp1=max(fileno(fp), sockfd)+1;
Select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset)) {//socket is readable
if( (n=Read(sockfd, buf, 1000))==0){
if(stdineof==1)
return;//normal termination
else
err_quit("cli_echo: server terminated prematurely");
}
Write(fileno(stdout),buf,n);
}
if(FD_ISSET(fileno(fp), &rset)){//input is readable
if( (n=Read(fileno(fp),buf,1000))==0){
stdineof=1;
Shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(fp), &rset);
continue;
}
Writen(sockfd, buf, n);
}
}
}
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if(argc!=2)
err_quit("usage: tcpcli <IPaddress>");
sockfd=Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(1234);
Inet_pton(AF_INET,argv[1], &servaddr.sin_addr);
Connect(sockfd, (SA*) &servaddr, sizeof(servaddr));
cli_echo(stdin,sockfd);
exit(0);
}
服务器端的程序
#include "unp.h"
#include <time.h>
void srv_echo(FILE *fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char buf[1000];
int n;
stdineof=0;
FD_ZERO(&rset);
for(;;){
if(stdineof==0)
FD_SET(fileno(fp),&rset);
FD_SET(sockfd,&rset);
maxfdp1=max(fileno(fp), sockfd)+1;
Select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset)) {//socket is readable
if( (n=Read(sockfd, buf, 1000))==0){
if(stdineof==1)
return;//normal termination
else
err_quit("srv_echo: client terminated prematurely");
}
Write(fileno(stdout),buf,n);
}
if(FD_ISSET(fileno(fp), &rset)){//input is readable
if( (n=Read(fileno(fp),buf,1000))==0){
stdineof=1;
Shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(fp), &rset);
continue;
}
Writen(sockfd, buf, n);
}
}
}
int
main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM,0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(1234);
Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
clilen=sizeof(cliaddr);
connfd=Accept(listenfd, (SA*) &cliaddr, &clilen);
srv_echo(stdin,connfd);
Close(connfd);
return 0;
}
实现结果:
1. 先开启服务端 ./srv_echo
2. 再开启客户端 ./cli_echo 127.0.0.1
3. 任意在服务端或者客户端输入内容, 对端都将收到该内容