TCP网络编程

UDP特点:

1.不安全不可靠的传输方式

2.UDP资源开销小,实现机制简单

3.UDP是无连接的(面向数据包)

TCP:

发送端:

1.创建用来通信的套接字(socket)

2.发送连接请求(connect)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
          功能:
            向接收方发起连接请求
          参数:
            sockfd:套接字文件描述符
            addr:接收方的IP地址和端口号
            addrlen:接收方的IP地址和端口号的大小
          返回值:
            成功返回0 
            失败返回-1 

3.发送数据(send)

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
          功能:
            向接收方发送数据
          参数:
            sockfd:套接字文件描述符
            buf:要发送的数据的首地址 
            len:要发送的数据的长度
            flags:标志位 
          返回值:
            成功返回发送字节数
            失败返回-1 

4.接收数据(recv)

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
          功能:
            接收发送方发送的数据
          参数:
            sockfd:套接字文件描述符
            buf:接收数据的缓冲区首地址
            len:接收数据的缓冲区的大小
            flags:标志位 
          返回值:
            成功返回实际接收字节数
            失败返回-1 
            对方关闭返回0 

5.关闭(close)

接收端:

1.创建套接字(socket)

2.绑定IP地址和端口号(bind)

3.监听(listen)

 int listen(int sockfd, int backlog);
        功能:
            监听发送三次握手连接的套接字,并放入等到处理队列中
        参数:
            sockfd:套接字文件描述符
            backlog:等待队列的大小(最多存放尚未被处理的三次握手请求的个数)
        返回值:
            成功返回0 
            失败返回-1 

4.处理连接请求(accept)

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
          功能:
              处理等待队列中的第一个套接字
          参数:
              sockfd:套接字文件描述符 
              addr:存放发送方IP地址的空间首地址
              addrlen:存放发送方IP地址的空间大小
          返回值:
              成功返回一个新的文件描述符
              失败返回-1 

5.收发(同上)

6.关闭

练习:

练习:使用TCP实现全双工聊天(线程实现)

send.c

#include "../head.h"
pthread_t tid1;
pthread_t tid2;
int sockfd = 0;

void *threadfun1(void *arg){
    char tmpbuff[1024] = {0};
    ssize_t nsize = 0;
    ssize_t nret = 0;
    while(1){
        memset(tmpbuff,0,sizeof(tmpbuff));
        fgets(tmpbuff,sizeof(tmpbuff),stdin);
        tmpbuff[strlen(tmpbuff)-1] = '\0';
        nsize = send(sockfd,tmpbuff,strlen(tmpbuff),0);
        if(-1 == nsize){
            perror("fail to send");
            return NULL;
        }
        if(!strcmp(tmpbuff,"quit")){
            break;
        }
    }
    pthread_cancel(tid2);
    return NULL;
}
void *threadfun2(void *arg){
    char tmpbuff[1024] = {0};
    ssize_t nsize = 0;
    ssize_t nret = 0;
    while(1){
        memset(tmpbuff,0,sizeof(tmpbuff));
        nsize = recv(sockfd,tmpbuff,sizeof(tmpbuff),0);
        if(-1 == nsize){
            perror("fail to send");
            return NULL;
        }
        if(!strcmp(tmpbuff,"quit")){
            break;
        }
        printf("SEND:%s\n",tmpbuff);
    }
    pthread_cancel(tid1);
    return NULL;
}


int main(void){
    

    struct sockaddr_in recvaddr;
    int ret = 0;
     ssize_t nsize = 0;

    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if( -1 == sockfd){
        perror("fali to socket");
        return -1;
    }

    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(RECV_PORT);
    recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);

    
    ret =  connect(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
    if(-1 == ret){
        perror("fail to connect");
        return -1;
    }

    pthread_create(&tid1,NULL,threadfun1,NULL);
    pthread_create(&tid2,NULL,threadfun2,NULL);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
     

   
    close(sockfd);
    return 0;
}

recv.c

#include "../head.h"
pthread_t tid1;
pthread_t tid2;
int confd = 0;

void *threadfun1(void *arg){
    char tmpbuff[1024] = {0};
    ssize_t nsize = 0;
    while(1){
        memset(tmpbuff,0,sizeof(tmpbuff));
        fgets(tmpbuff,sizeof(tmpbuff),stdin);
        tmpbuff[strlen(tmpbuff)-1] = '\0';
        nsize = send(confd,tmpbuff,strlen(tmpbuff),0);
        if(-1 == nsize){
            perror("fail to send");
            return NULL;
        }
        if(!strcmp(tmpbuff,"quit")){
            break;
        }
    }
    pthread_cancel(tid2);
    return NULL;
}
void *threadfun2(void *arg){
    char tmpbuff[1024] = {0};
    ssize_t nsize = 0;
    ssize_t nret = 0;
    while(1){
        memset(tmpbuff,0,sizeof(tmpbuff));
        nsize = recv(confd,tmpbuff,sizeof(tmpbuff),0);
        if(-1 == nsize){
            perror("fail to send");
            return NULL;
        }
        if(!strcmp(tmpbuff,"quit")){
            break;
        }
        printf("RECV:%s\n",tmpbuff);
    }
    pthread_cancel(tid1);
    return NULL;
}


int main(void){
    int sockfd = 0;
    struct sockaddr_in recvaddr;
    struct sockaddr_in sendaddr;
    socklen_t len = sizeof(sendaddr);
    int ret = 0;

    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if( -1 == sockfd){
        perror("fali to socket");
        return -1;
    }
    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(RECV_PORT);
    recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);

    ret = bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
    if(-1 == ret){
        perror("fail to bind");
        return -1;
    }

    ret = listen(sockfd,10);
    if(-1 == ret){
        perror("fail to listen");
        return -1;
    }

    confd = accept(sockfd,(struct sockaddr*)&sendaddr,&len);
     if(-1 == ret){
        perror("fail to accept");
        return -1;
     }

    pthread_create(&tid1,NULL,threadfun1,NULL);
    pthread_create(&tid2,NULL,threadfun2,NULL);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
     

   
    close(confd);
    close(sockfd);
    return 0;
}

 

练习:使用UDP完成聊天室功能(进程实现)

send.c

#include "../head.h"

int main(void){
    int sockfd = 0;
    struct sockaddr_in recvaddr;
    char tmpbuff[1024] = {0};
    ssize_t nszie = 0;
    pid_t pid = 0;

    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd){
        perror("fail to socket");
        return -1;
    }

    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(RECV_PORT);
    recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);

    nszie = sendto(sockfd,"a",2,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
    if(-1 == nszie){
        perror("fail to sendto");
        return -1;
    }
    pid = fork();
    if(-1 == pid){
        perror("fail to fork");
        return -1;
    }
    if(pid == 0){
        while (1)
        {
            memset(tmpbuff,0,sizeof(tmpbuff));
            fgets(tmpbuff,sizeof(tmpbuff),stdin);
            tmpbuff[strlen(tmpbuff)-1] = '\0';

            nszie = sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
            if(-1 == nszie){
            perror("fail to sendto");
            return -1;
            }
            if(strcmp(tmpbuff,"quit") ==0){
                break;
            }
        }
         kill(getppid(),SIGKILL);
        
    }else if(pid > 0){
        while(1){
            memset(tmpbuff,0,sizeof(tmpbuff));
            nszie = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);
            if(-1 == nszie){
                perror("fail to recvfrom");
                return -1;
            }
            if(strcmp(tmpbuff,"quit")== 0){
                break;
            }
            printf("%s:%d->%s\n",inet_ntoa(recvaddr.sin_addr),ntohs(recvaddr.sin_port),tmpbuff);
        }
         kill(pid,SIGKILL);
    }
  
    close(sockfd);
    return 0;
}

recv.c

#include "../head.h"

int main(void){
    int sockfd = 0;
    struct sockaddr_in recvaddr;
    struct sockaddr_in sendaddr;
    char tmpbuff[1024] = {0};
    ssize_t nszie = 0;
    pid_t pid = 0;
    int ret = 0;
    socklen_t addlen = sizeof(sendaddr);

    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd){
        perror("fail to socket");
        return -1;
    }

    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(RECV_PORT);
    recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);

   ret = bind(sockfd,(struct sockaddr*)&recvaddr,sizeof(recvaddr));
   if (-1 == ret)
    {
        perror("fail to bind");
        return -1;
    }

    nszie = recvfrom(sockfd,tmpbuff,sizeof(recvaddr),0,(struct sockaddr *)&sendaddr,&addlen);
    if(-1 == nszie){
        perror("fail to sendto");
        return -1;
    }
    printf("%s:%d->%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),tmpbuff);

    pid = fork();
    if(-1 == pid){
        perror("fail to fork");
        return -1;
    }
    if(pid == 0){
        while(1){
            memset(tmpbuff,0,sizeof(tmpbuff));
            fgets(tmpbuff,sizeof(tmpbuff),stdin);
            tmpbuff[strlen(tmpbuff)-1] = '\0';

            nszie = sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&sendaddr,sizeof(sendaddr));
            if(-1 == nszie){
                perror("fail to sendto");
                return -1;
            }
            if(strcmp(tmpbuff,"quit") == 0){
                break;
            }
        }
        kill(getppid(),SIGKILL);
      
    }else if(pid > 0){
        while(1){
            memset(tmpbuff,0,sizeof(tmpbuff));
            nszie = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);
            if(-1 == nszie){
                perror("fail to recvfrom");
                return -1;
            }
           if(strcmp(tmpbuff,"quit") == 0){
                break;
            }
            printf("%s:%d->%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),tmpbuff);
        }
        kill(pid,SIGKILL);
    }
    close(sockfd);

    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值