bingbingc(网络编程TCP UDP)

Posted 月屯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bingbingc(网络编程TCP UDP)相关的知识,希望对你有一定的参考价值。

上一篇

目录标题

参考

字节序

  • 小端字节序:低位放在低地址
  • 大端字节序:低位放在高地址
  • 主机字节序:指的是机器本身的字节序,如果是大端,则主机字节序为大端。如果是小端,则主机字节序为小端
  • 网络字节序:规定网络传输数据的时候采用大端字节序进行传输

字节序转化

TCP和UDP


UDP socket编程

创建套接字的含义
将进程和网卡进行绑定,进程可以从网卡当中接收数据,也可以通过网卡发送数据
绑定地址信息的含义:
绑定ip,绑定端口,是为了在网络当中可以标识出来一台主机和一个进程。

  • 对于接收方而言:发送数据的人就知道接收方在那台机器那个进程了
  • 对于发送方而言:能标识网络数据从那台机器那个进程发送出去的

接口


 netstat -anp |grep 28989// 端口占用情况



编码

客户端

#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>
using namespace std; 
int main()
  int sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if(sockfd<0)
    perror("socker failed");
  
  else 
    cout<<"socker "<<sockfd<<endl;
  struct sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_port=htons(28989);
  addr.sin_addr.s_addr=inet_addr("172.17.0.1");//可私网或公网

  const char*  str="hello\\n";
  sendto(sockfd,str,strlen(str),0,(struct sockaddr*)&addr,sizeof(addr));
  close(sockfd);
  return 0;


服务端

#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std; 
int main()
  int sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if(sockfd<0)
    perror("socker failed");
  
  else 
    cout<<"socker "<<sockfd<<endl;
  struct sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_port=htons(28989);
  addr.sin_addr.s_addr=inet_addr("172.17.0.1");//必须是私网
  int ret=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
  if(ret<0)
    perror("bind failed");
  
  
char buf[1024]=0;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len=sizeof(cli_addr);
ssize_t recv_size=recvfrom(sockfd,buf,sizeof(buf)-1,0,(struct sockaddr*)&cli_addr,&cli_addr_len);
cout<<buf;
close(sockfd);
  return 0;



完善
server

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main()
    /*
     * 1.创建套接字
     * */
    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd < 0)
        perror("socket");
        return 0;
    
    printf("sockfd is %d\\n", sockfd);

    /*
     * 2.绑定地址信息
     * */
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(28989);
    /*
     * in_addr_t inet_addr(const char *cp);
     *    1.将点分十进制的ip转化成为无符号的32位整数
     *    2.将无符号32位整数转换成为网络字节序
     * */
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");

    int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0)
        perror("bind");
        return 0;
    


    while(1)
        char buf[1024] = 0;
        struct sockaddr_in cli_addr;
        socklen_t cli_addr_len = sizeof(cli_addr);
        ssize_t recv_size = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr*)&cli_addr, &cli_addr_len);
        if(recv_size < 0)
            return 0;
        
    
        //ip:port client say:
        printf("%s:%d client say:%s\\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);

        //发送数据
        // hello, ip:port, i am server;
        memset(buf, '0', sizeof(buf));
        sprintf(buf, "hello, %s:%d, i am server~", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));

        sleep(1);

        sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&cli_addr, sizeof(cli_addr));
    



    close(sockfd);
    return 0;

client

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <iostream>
using namespace std;

void UseAge()
    printf("use command : ./udp_client [ip] [port]\\n");


int main(int argc, char* argv[])
    /*
     * ./udp_client ip port
     * */
    if(argc != 3)
        UseAge();
        return 0;
    

    char* ip = argv[1];
    uint16_t port = atoi(argv[2]);

    /*
     * 1.创建套接字
     * */
    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd < 0)
        perror("socket");
        return 0;
    
    printf("sockfd is %d\\n", sockfd);

    struct sockaddr_in dest_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);
    /*
     * in_addr_t inet_addr(const char *cp);
     *    1.将点分十进制的ip转化成为无符号的32位整数
     *    2.将无符号32位整数转换成为网络字节序
     * */
    dest_addr.sin_addr.s_addr = inet_addr(ip);

    /*
     * 2.发送数据
     * */
    while(1)
        char buf[1024] = 0;
        printf("cli# ");
        fflush(stdout);
        cin >> buf;
        ssize_t send_size = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
        if(send_size < 0)
            return 0;
        

        memset(buf, '\\0', sizeof(buf));

        recvfrom(sockfd, buf, sizeof(buf) - 1, 0, NULL, NULL);
        printf("%s\\n", buf);
    

    close(sockfd);
    return 0;

TCP

  • 监听的含义:监听tcp客户端新的链接,同客户端建立tcp连接。注意:这个时候,TCP连接的建立在内核当中就完成了
  • 获取新连接的含义:获取新连接的套接字描述符,每一个TCP连接会产生一个套接字描述符
  • 发起连接的含义:向服务端发起TCP连接

接口


检查连接是否成功


成功无提示,失败提示失败

代码

单线程

客户端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>

using namespace std;

int main()
    /*
     * 1.创建侦听套接字
     * 2.绑定
     * 3.监听
     * */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
        perror("listen_fd");
        return 0;
    

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(28989);
    addr.sin_addr.s_addr = inet_addr("42.192.83.143");


    int ret = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0)
        perror("connect");
        return 0;
    

    while(1)
        char buf[1024] = 0;
        cout << "please enter your msg# ";
        fflush(stdout);

        cin >> buf;
        ssize_t send_size = send(sockfd, buf, strlen(buf), 0);
        if(send_size < 0)
            continue;
        

        memset(buf, '\\0', sizeof(buf));
        ssize_t  recv_size = recv(sockfd, buf, sizeof(buf) - 1, 0);
        if(recv_size < 0)
            continue;
        else if(recv_size == 0)
            printf("server shutdown connect\\n");
            break;
        
        printf("%s\\n", buf);
    
   
    close(sockfd);
    return 0;

服务端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main()
    /*
     * 1.创建侦听套接字
     * 2.绑定
     * 3.监听
     * */
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_fd < 0)
        perror("listen_fd");
        return 0;
    

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(28989);
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    int ret = bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0)
        perror("bind");
        return 0;
    

    ret = listen(listen_fd, 5);
    if(ret < 0)
        perror("listen");
        return 0;
    

    struct sockaddr_in cli_addr;
    socklen_t cli_addr_len = sizeof(cli_addr);
    int new_sockfd = accept(listen_fd, (struct sockaddr*)&cli_addr, &cli_addr_len);
    if(new_sockfd < 0)
        perror("accept");
        return 0;
    
    while(1)



        char buf[1024] = 0;
        ssize_t recv_size = recv(new_sockfd, buf, sizeof(buf) - 1, 0);
        if(recv_size < 0)
            perror("recv");
            continue;
        else if(recv_size == 0)
            printf("peer shutdown!!\\n");
            close(new_sockfd);
            return 0;
        

        printf("buf is [%s]\\n", buf);

        memset(buf, '\\0', sizeof(buf));
        sprintf(buf, "[%s]:[%d], i am server, i recv your msg", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));

        send(new_sockfd, buf, strlen(buf), 0);
    
    close(listen_fd);
    return 0;

结论:单线程的程序,由于accept和recv都阻塞的特性,导致:
1.如果accept和recv都进行循环调用,会导致accept阻塞影响recv的接收,或者recv阻塞影响accept获取新连接,并且,accept接收回来的新连接套接字B会覆盖之前的新连接套接字A

多进程服务端

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/wait.h>

#define Judge_ret(ret)if(ret < 0)return 0;

void sigcallback(int signum)
    wait(NULLbingbingc(网络编程TCP UDP)

bingbingc(网络编程TCP UDP)

socket编程

校验TCP和UDP的校验和

Java网络编程之UDP和TCP套接字

TCP和UDP网络编程