socket編程-select學習

這個可以實現羣發消息,客戶端連接上後發送的消息除了自己其他客戶端都可以看到
服務器端-C語言
頭文件

#include<unistd.h>
#include <netinet/in.h> 
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/select.h>
#include<sys/time.h>
#include<stdlib.h>
#include<limits.h>
#include<error.h>
#include<math.h>
#define MAXLINE 1024
char recvline[MAXLINE];
char sendline[MAXLINE];

主函數

#include"unp.h"
int main(int argc,char * argv[])
{
    int i,maxi,maxfd,listenfd,connfd,sockfd,j;
    int nready,client[FD_SETSIZE];
    ssize_t n;
    fd_set rset,allset;
    char    buf[MAXLINE],buf1[MAXLINE];
    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_port=htons(9880);
//servaddr.sin_addr.s_addr=htonl("127.0.0.1");  爲啥不能用htonl
    servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
    //測試的是自己本機,要想測其他本機記得改IP哦.

    bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));

    listen(listenfd,5);

    maxfd=listenfd;
    maxi=-1;
    for(i=0;i<FD_SETSIZE;i++)
        client[i]=-1;
    FD_ZERO(&allset);
    FD_SET(listenfd,&allset);
    for(;;)
    {
        rset=allset;
        nready=select(maxfd+1,&rset,NULL,NULL,NULL);

        if(FD_ISSET(listenfd,&rset))
        {
            clilen=sizeof(cliaddr);
            connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);
            printf("%d\n",connfd);
            for(i=0;i<FD_SETSIZE;i++)
            {
                if(client[i]<0)
                {
                    client[i]=connfd;
                    break;
                }
            }
            if(i==FD_SETSIZE)
                perror("too many clients");

            FD_SET(connfd,&allset);
            if(connfd>maxfd)
                maxfd=connfd;
            if(i>maxi)
                maxi=i;
            if(--nready<=0)
                continue;
        }
        for(i=0;i<=maxi;i++)
        {
            if((sockfd=client[i])<0)
                continue;
            if(FD_ISSET(sockfd,&rset))
            {
#if 1               
                if( (n=read(sockfd,buf1,MAXLINE)) ==0)
                {
                    close(sockfd);
                    FD_CLR(sockfd,&allset);
                    client[i]=-1;
                }
                else
                {   //把客戶端的IP和信息寫進buf,發送給其他用戶
                    sprintf(buf,"%s-----%s",inet_ntoa(cliaddr.sin_addr),buf1);
                    for(j=0;j<=maxi;j++)
                        if(client[j]!=sockfd)
                            write(client[j],buf,strlen(buf)+1);
                }
#endif
#if 0
                if( (n=read(sockfd,buf,MAXLINE)) ==0)
                {
                    close(sockfd);
                    FD_CLR(sockfd,&allset);
                    client[i]=-1;
                }
                else
                {
                    for(j=0;j<=maxi;j++)
                        if(client[j]!=sockfd)
                            write(client[j],buf,n);
                }
#endif
                if(--nready<=0)
                    break;
            }
        }
    }

    return 0;
}

客戶端-C++
頭文件

#include<iostream>
using namespace std;
#include<algorithm>
#include<unistd.h>
#include <netinet/in.h> 
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/select.h>
#include<sys/time.h>
#include<stdlib.h>
#include<limits.h>
#include<error.h>
#include<math.h>
#define MAXLINE 1024

char recvline[MAXLINE];
char sendline[MAXLINE];

主函數

#include"util.h"
void str_cli(FILE *fp,int sockfd)
{
    int maxfdp1,stdineof;
    fd_set rset;
    char buf[MAXLINE];
    int n;
    stdineof=0;
    FD_ZERO(&rset);
    char s1[1024],s2[1024];
    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))
        {
            if((n=read(sockfd,buf,MAXLINE))==0)
            {
                if(stdineof==1)
                    return;
                else
                    perror("strcli:server terminated prematurely");
            }
            sscanf(buf,"%s",s1);
            cout<<s1<<"  "<<endl;
            //write(fileno(stdout),buf,n);
        }
        if(FD_ISSET(fileno(fp),&rset))
        {
            if((n=read(fileno(fp),buf,MAXLINE))==0)
            {
                stdineof=1;
                shutdown(sockfd,SHUT_WR);
                FD_CLR(fileno(fp),&rset);
                continue;
            }
            write(sockfd,buf,n);
        }
    }
}
int main(int argc,char *argv[])
{
    int sockfd;
    struct sockaddr_in servaddr;
    if(argc!=2)
        perror("usage:tcpcli <IPadress>");
    sockfd=socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(9880);
    inet_pton(AF_INET,argv[1],&servaddr.sin_addr);

    connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));

    str_cli(stdin,sockfd);

    exit(0);

}

遇到的問題:
1.#include<netinet/in.h>這個頭文件還是不太懂它是哪個結構體或函數需要引入;看別人說struct sockaddr這和結構體需要
2.servaddr.sin_addr.s_addr=htonl(“127.0.0.1”); 會報錯,不懂.
3.sprintf(buf,”%s\t\t%s”,inet_ntoa(cliaddr.sin_addr),buf1);
寫’\t\t’發的信息會出現亂碼;
sprintf(buf,”%s    %s”,inet_ntoa(cliaddr.sin_addr),buf1);
寫成空格運行不了. 不是很懂.
編譯:
gcc server.c -o server
g++ client.c -o client
./server
./client
運行結果

第一個用戶
这里写图片描述
第二個用戶
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值