TCP并发服务器

TCP并发服务器

NOTE(重重难难点):

socket返回的套接字描述符和accept返回的套接字描述符???

S: accept默认会阻塞进程,直到有一个客户连接建立后返回,它返回的是一个新可用的套接字,这个套接字是连接套接字。此时我们需要区分两种套接字,一种套接字正如accept的参数sockfd,它是监听套接字,在调用listen函数之后,一个套接字会从主动连接的套接字变身为一个监听套接字;而accept返回是一个连接套接字,它代表着一个网络已经存在的点点连接。


TCP并发服务器代码:

#服务器
#include <sys/socket.h> 
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#define portnum 3333

int main()
{
    int sockfd;
    int new_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    
    char buffer[128];
    
    int sin_size;
    
    //1. 创建套接字   
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    
    if(sockfd==-1)
    {
        printf("create socket error!");
        exit(1);
    }
    
    //2. 绑定地址
    bzero(&server_addr, sizeof(struct sockaddr_in));//清零
    server_addr.sin_family = AF_INET; //协议族
    server_addr.sin_port = htons(portnum); //端口号  主机字节序->网络字节序
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY 可以使用主机任意一个ip地址 主机字节序->网络字节序    
    
    //绑定
    bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
    
    //3. 监听端口
    listen(sockfd,5);//5-允许连接客户机的数目
    while(1)
    {
        //4. 等待连接    
        sin_size = sizeof(struct sockaddr);
        new_fd = accept(sockfd,(struct sockaddr *)&client_addr, &sin_size);
        
        printf("server get connection from %s\n",inet_ntoa(client_addr.sin_addr));
    
    
        //创建子进程,由子进程处理数据
        int pid;
        pid = fork();
        if(pid == 0)
        {
            //5. 收发数据
            int nbyte;//实际接受的长度
            nbyte = recv(new_fd,buffer,128,0); //使用连接产生的新的fd
        
            buffer[nbyte]='\0';
            printf("server received: %s\n",buffer);
            
            //5. 结束连接
            close(new_fd); 
        }
        else if(pid < 0)
            printf("fork err\n");
    }
    
    close(sockfd);
    
    return 0;
}
#客户端
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#define portnum 3333

int main()
{
    int sockfd;
    struct sockaddr_in server_addr;
    
    char buffer[128];
    
    //1.创建套接字
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    
    if(sockfd == -1)
    {
    	printf("create socket error");
    	exit(1);
    }
    
    //2.请求连接
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(portnum);
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.103");
    
    int con_s;
    con_s = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr));
    
    if(con_s == -1)
    {
    	printf("connect fail!\n");
    	exit(1);
    }       
    
    //3.收发数据
    printf("Please input some char: \n");
    fgets(buffer,128,stdin);

    send(sockfd,buffer,strlen(buffer),0);
    
    //4.关闭连接
    close(sockfd);
    
    return 0;
}


popen重写 /* * ===================================================================================== * * Filename: tcpserver.c * * Description: this program is demostrate to how to write a remote control server * * Version: 1.0 * Created: 2010年09月11日 21时28分21秒 * Revision: none * Compiler: gcc * * Author: Gang Liang (cs.scu.edu.cn/~lianggang), lianggang@scu.edu.cn * Company: Sichuan university * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #define PORT 8900 #define BUFSIZE 2048 #define SHELL "/bin/sh" FILE *myPopen(char *command,char *type) { int f_des[2]; int pid_t; // pipe(f_des); if((type[0]!='r'&&type[0]!='w')||type[1]!=0) { printf("myPopen()flag error/n"); return NULL; } if(pipe(f_des)==-1) { printf("pipe create error/n"); return NULL; } pid_t=fork(); if(pid_t<0) return NULL; if(pid_t==0) { if(type[0]=='r') { close(f_des[0]); dup2(f_des[1],STDOUT_FILENO); close(f_des[1]); } else{ close(f_des[1]); dup2(f_des[0],STDIN_FILENO); close(f_des[0]); } execl(SHELL,"sh","-c",command,(char*)0); _exit(127); char *argv[] = {command,0}; if(execvp(command,argv)==-1) return NULL; } wait(0); if(type[0]=='r') { close(f_des[1]); return fdopen(f_des[0],"r"); } else{ close(f_des[0]); return fdopen(f_des[1],"w"); } } int execute(char*command,char*buf) { FILE *fp; int count; char commandbuf[2056]; if ((NULL==command)||(NULL==buf)) { perror("command or buf is empty\n"); return -1; } count =0; memset(commandbuf,0,2056); strcat(commandbuf,"sh -c "); strcat(commandbuf,command); fprintf(stderr,"the command is %s\n",commandbuf); if (NULL==(fp=myPopen(commandbuf,"r"))) { perror("create pipe error\n"); return -1; } while ((count<2047) && (EOF!=(buf[count++]=fgetc(fp)))); buf[count-1]='\0'; return count; } int main() { int sockfd; int conn_sock; char sendbuf[BUFSIZE]; char recvbuf[BUFSIZE]; int sendnum; int recvnum; int length; struct sockaddr_in client; struct sockaddr_in server; int opt; int cnt; pid_t pid; /* The first stage:INITILIZE */ memset(&client,0,sizeof(client)); memset(&server,0,sizeof(server)); memset(sendbuf,0,BUFSIZE); memset(recvbuf,0,BUFSIZE); length=0; sockfd=-1; conn_sock=-1; opt=SO_REUSEADDR; /*The second stage:create listen socket */ if (-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))) { perror("create socket error\n"); return -1; } setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); /* The third stage:bind socket */ server.sin_family=AF_INET; server.sin_addr.s_addr=htonl(INADDR_ANY); server.sin_port=htons(PORT); if (-1==bind(sockfd,(struct sockaddr*)&server,sizeof(server))) { perror("bind socket error\n"); close(sockfd); return -1; } /* The fourth stage:listen socket */ if (-1==listen(sockfd,10)) { perror("listen socket error\n"); close(sockfd); return -1; } /* The fifth stage:creat connect socket */ while(1) { if (-1==(conn_sock=accept(sockfd,(struct sockaddr*)&client,&length))) { perror("three shakehands error\n"); close(sockfd); return -1; } /* the commnication with client */ pid=fork(); if(pid==0) { close(sockfd); while(1) { memset(recvbuf,0,BUFSIZE); memset(sendbuf,0,BUFSIZE); if (0>=(recvnum=read(conn_sock,recvbuf,BUFSIZE))) { perror("the commucation error\n"); close(conn_sock); close(sockfd); return -1; } recvbuf[recvnum]='\0'; fprintf(stderr,"the command is:%s\n",recvbuf); if (0==strcmp(recvbuf,"quit")) { fprintf(stderr,"the client is quit\n"); close(conn_sock); break; } if (1>=(cnt=execute(recvbuf,sendbuf))) { sprintf(sendbuf,"the invalid command,please try again\n"); } fprintf(stderr,"the result is \n%s",sendbuf); if (0>=(sendnum=write(conn_sock,sendbuf,strlen(sendbuf)))) { perror("the commucation error\n"); close(sockfd); close(conn_sock); return -1; } } } else if(pid>0) { close(conn_sock); continue; } } close(sockfd); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值