聊天程序的简单实现

功能:

实现两个主机之间的局域网聊天


实现关键:

如何同时处理套接字的输入和标准输入 --- select函数


客户端的程序

  1. #include "unp.h"
  2. void cli_echo(FILE *fp, int sockfd)
  3. {
  4. int maxfdp1, stdineof;
  5. fd_set rset;
  6. char buf[1000];
  7. int n;
  8. stdineof=0;
  9. FD_ZERO(&rset);
  10. for(;;){
  11. if(stdineof==0)
  12. FD_SET(fileno(fp),&rset);
  13. FD_SET(sockfd,&rset);
  14. maxfdp1=max(fileno(fp), sockfd)+1;
  15. Select(maxfdp1, &rset, NULL, NULL, NULL);
  16. if(FD_ISSET(sockfd, &rset)) {//socket is readable
  17. if( (n=Read(sockfd, buf, 1000))==0){
  18. if(stdineof==1)
  19. return;//normal termination
  20. else
  21. err_quit("cli_echo: server terminated prematurely");
  22. }
  23. Write(fileno(stdout),buf,n);
  24. }
  25. if(FD_ISSET(fileno(fp), &rset)){//input is readable
  26. if( (n=Read(fileno(fp),buf,1000))==0){
  27. stdineof=1;
  28. Shutdown(sockfd, SHUT_WR);
  29. FD_CLR(fileno(fp), &rset);
  30. continue;
  31. }
  32. Writen(sockfd, buf, n);
  33. }
  34. }
  35. }
  36. int
  37. main(int argc, char **argv)
  38. {
  39. int sockfd;
  40. struct sockaddr_in servaddr;
  41. if(argc!=2)
  42. err_quit("usage: tcpcli <IPaddress>");
  43. sockfd=Socket(AF_INET, SOCK_STREAM, 0);
  44. bzero(&servaddr, sizeof(servaddr));
  45. servaddr.sin_family=AF_INET;
  46. servaddr.sin_port=htons(1234);
  47. Inet_pton(AF_INET,argv[1], &servaddr.sin_addr);
  48. Connect(sockfd, (SA*) &servaddr, sizeof(servaddr));
  49. cli_echo(stdin,sockfd);
  50. exit(0);
  51. }

服务器端的程序

  1. #include "unp.h"
  2. #include <time.h>
  3. void srv_echo(FILE *fp, int sockfd)
  4. {
  5. int maxfdp1, stdineof;
  6. fd_set rset;
  7. char buf[1000];
  8. int n;
  9. stdineof=0;
  10. FD_ZERO(&rset);
  11. for(;;){
  12. if(stdineof==0)
  13. FD_SET(fileno(fp),&rset);
  14. FD_SET(sockfd,&rset);
  15. maxfdp1=max(fileno(fp), sockfd)+1;
  16. Select(maxfdp1, &rset, NULL, NULL, NULL);
  17. if(FD_ISSET(sockfd, &rset)) {//socket is readable
  18. if( (n=Read(sockfd, buf, 1000))==0){
  19. if(stdineof==1)
  20. return;//normal termination
  21. else
  22. err_quit("srv_echo: client terminated prematurely");
  23. }
  24. Write(fileno(stdout),buf,n);
  25. }
  26. if(FD_ISSET(fileno(fp), &rset)){//input is readable
  27. if( (n=Read(fileno(fp),buf,1000))==0){
  28. stdineof=1;
  29. Shutdown(sockfd, SHUT_WR);
  30. FD_CLR(fileno(fp), &rset);
  31. continue;
  32. }
  33. Writen(sockfd, buf, n);
  34. }
  35. }
  36. }
  37. int
  38. main(int argc, char **argv)
  39. {
  40. int i, maxi, maxfd, listenfd, connfd, sockfd;
  41. socklen_t clilen;
  42. struct sockaddr_in cliaddr, servaddr;
  43. listenfd = Socket(AF_INET, SOCK_STREAM,0);
  44. bzero(&servaddr, sizeof(servaddr));
  45. servaddr.sin_family=AF_INET;
  46. servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  47. servaddr.sin_port=htons(1234);
  48. Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
  49. Listen(listenfd, LISTENQ);
  50. clilen=sizeof(cliaddr);
  51. connfd=Accept(listenfd, (SA*) &cliaddr, &clilen);
  52. srv_echo(stdin,connfd);
  53. Close(connfd);
  54. return 0;
  55. }


实现结果:

1. 先开启服务端 ./srv_echo

2. 再开启客户端 ./cli_echo 127.0.0.1

3. 任意在服务端或者客户端输入内容, 对端都将收到该内容







附件列表

    原文地址:https://www.cnblogs.com/gremount/p/5803107.html