Linux C: 基于C/S的多线程网络编程 (服务器充当一个客户端的两点传输)

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<arpa/inet.h>  
#include<unistd.h>  
#include<signal.h>  
#include<pthread.h>  
  
int tcp_init(const char* ip, int port)  //用于初始化  
{  
    int sfd = socket(AF_INET, SOCK_STREAM, 0); //首先建立一个Socket,向系统申请  
    if(sfd == -1)  
    {  
        perror("Socket error\n");  
        exit(1);  
    }  
    struct sockaddr_in serveraddr;  
    memset( &serveraddr, 0, sizeof(struct sockaddr) );   
    serveraddr.sin_family = AF_INET;  
    serveraddr.sin_port = htons(port);   
    //将主机的无符号短整形数转换成网络字节顺序。hostshort:主机字节顺序表达的16位数  
    serveraddr.sin_addr.s_addr = inet_addr(ip); //或者INADDR_ANY  
    //将新的socket和制定的ip、port绑定  
    if(bind(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)) == -1)  
    {  
        perror("Bind Error");  
        close(sfd);  
        exit(-1);  
    }  
    if(listen(sfd, 10) == -1)  //监听它 最大连接数为10  
    {  
        perror("Listen error");   
        close(sfd);  
        exit(-1);  
    }  
    return sfd;  
}  
  
int tcp_accept(int sfd)  
{  
    struct sockaddr_in clientaddr;  
    memset(&clientaddr, 0, sizeof(struct sockaddr) );  
    unsigned int addrlen = sizeof(struct sockaddr);  
    int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);  
    //sfd接受客户端的连接,创建新的socket为new_fd, 将请求连接的客户端IP  
    //port保存在结构体clientaddr中  
    if(new_fd == -1)  
    {  
        perror("accept error");  
        close(sfd);  
        exit(-1);  
    }  
    printf("%s %d success connect...\n", inet_ntoa(clientaddr.sin_addr),  
                    ntohs(clientaddr.sin_port));  
    //inet_ntoa:函数功能:将网络地址转换成“.”点隔的字符串格式。  
    return new_fd;  
}  
  
void signalhandler(void)  
{  
    sigset_t sigSet;  
    sigemptyset(&sigSet);  
    sigaddset(&sigSet,SIGINT);  
    sigaddset(&sigSet,SIGQUIT);  
    sigprocmask(SIG_BLOCK,&sigSet,NULL);      
}  
  
typedef struct{  
    int sfd;  
    int cfd;  
}tcp_info;  
  
void* pthread_send(void *arg)  
{  
    tcp_info *temp;  
    temp = ( tcp_info *)arg;  
    char buf[128];  
    while(1)  
    {  
        memset(buf, 0, sizeof(buf));  
        scanf("%s",buf);  
        if(send(temp->cfd, buf, 128, 0) == -1)  
        {  
            perror("send");  
            close(temp->cfd);  
            close(temp->sfd);  
            exit(-1);  
        }  
        sleep(1);  
    }  
}  
  
void* pthread_recv(void *arg)  
{  
    char buf[128] = {0};  
    memset(buf, 0, sizeof(buf));  
    tcp_info *temp;  
    temp = ( tcp_info *)arg; 
    while(1)  
    {  
        if(recv(temp->cfd, buf, sizeof(buf), 0 ) == -1)  
        {  
            perror("recv");  
            close(temp->cfd);  
            close(temp->sfd);  
            exit(-1);  
        }  
        printf("\n");  
        puts(buf);  
    }  
}  
  
  
int main(int argc,char **argv)  
{  
    int ret_send;  
    int ret_recv;  
                  
    pthread_t id1;  
    pthread_t id2;  
                      
    if(argc < 3)  
    {  
        printf("usage:./servertcp ip port \n");  
        exit(-1);  
    }  
    signalhandler();  
    int sfd = tcp_init(argv[1], atoi(argv[2]));  
    //atoi:把字符串转化成整形的函数,例如atoi(“123”) = 123  
    //这里也可以这样写: int sfd = tcp_init("192.168.0.164",8888);  
    int cfd = tcp_accept(sfd);  
      
    tcp_info *info;   
    info = (tcp_info*)malloc(sizeof(tcp_info));  
    info->sfd = sfd;  
    info->cfd = cfd;  
  
    ret_send = pthread_create(&id1, NULL, pthread_send, (void*)info);  
    ret_recv = pthread_create(&id2, NULL, pthread_recv, (void*)info);   
      
  
    pthread_join(id1, NULL);  
    pthread_join(id2, NULL);  
  
    close(cfd);  
    close(sfd);   
    return 0;  
}  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值