Linux学习笔记-----网络编程套接字

2023-11-05

 

目录

 

一 、概念

(一)端口号概念

(二)套接字概念

(三)套接字(socket)编程接口

(四)sockaddr结构

(五)网络字节序

二、基于UDP的相关理解

(一)UDP协议

(二)编写简单的UDP服务端和客户端

(三)小结

三、基于TCP的相关理解

(一)TCP协议

(二)编写单执行流的TCP服务端和客户端

  (三)编写多进程的TCP服务端和客户端

(四)编写多线程的TCP服务端和客户端

(五)小结


一 、概念

(一)端口号概念

  • 端口号标定该主机上互联网中唯一一个进程。
  • 进程ID是每个进程都有的,但是端口号只有是网络进程才给指派端口号。
  • 一个端口号用来标识一个进程,一个进程可以绑定多个端口号。一个进程可以同时拥有端口和pid。
  • 传输层协议(TCP和UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号. 就是在描述 "数据是谁发的, 要发给谁"。

(二)套接字概念

  • 所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象,套接字编程本质是进程间通信。
  • IP号标定唯一主机,IP+端口号(PORT,16位bit)标识全网内唯一一个进程,也叫套接字。
  • 创建套接字,实际上是创建两套资源,第一套是通讯需要的网卡相关的资源,第二个是需要和文件系统挂钩的相关文件资源。

(三)套接字(socket)编程接口

  • socket返回值是一个文件描述符,数值默认是3,一个进程可以打开多个套接字,描述套接字的数据结构struct socket,进程和套接字是用过文件描述符表关联起来。

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)

  • int socket(int domain, int type, int protocol);
  • domain相当于采用哪种协议一般选择ipv4,type 一般使用SOCK_STREM对应的是TCP (面向字节流的,面向链接的) SOCK_DFRM(面向用户数据报是UDP,无链接的)返回值是int型,成功返回一个文件描述符。

 

// 绑定端口号 (TCP/UDP, 服务器)

//所谓绑定就是在a.填充进当前服务器的ip地址和端口号b.不同套接字的操作方法不一样,他要初始化底层的函数指针让它指向不同的标准方法。

  • int bind(int socket, const struct sockaddr *address,socklen_t address_len);

 

// 开始监听socket (TCP, 服务器)

  • int listen(int socket, int backlog);
  • backlog代表是底层链接队列长度是多少,一般不要设置太大。

 

// 接收请求 (TCP, 服务器)

  • int accept(int socket, struct sockaddr* address,socklen_t* address_len);
  • accept里的sockfd(lsock拉客的人)专注于从底层获取链接上来,返回值sockfd(服务员)专注于通信

 

// 建立连接 (TCP, 客户端)

  • int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
     

(四)sockaddr结构

  • socketaddr数据结构表示套接字的数据结构。
  • 有三类套接字,第一种是基于流式的,第二种是域间的(基于AF_INET叫做协议组),第三种是原始套接字。

(五)网络字节序

  • 默认网络跑的数据都是大端序列的。当发的是小端数据时,就需要转成大端。为了解决大小端问题,就引入网络字节序。网络是大端,本质是一种共识。
  • 网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big-endian(大端)排序方式。

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换:

  • 头文件:#include<arpa/inet.h>
  • htons把unsigned short类型从主机序转换到网络序。
  • htonl 把unsigned long类型从主机序转换到网络序。
  • ntohs 把unsigned short类型从网络序转换到主机序。
  • ntohl 把unsigned long类型从网络序转换到主机序。

二、基于UDP的相关理解

(一)UDP协议

  • 传输层协议
  • 无连接
  • 不可靠传输
  • 面向数据报
     

(二)编写简单的UDP服务端和客户端

//服务器 .hpp
#pragma once


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


  class udpServer{ 
    private:
        std::string ip;
        int port;
        int sock;
   public:
        udpServer(std::string _ip="127.0.0.1", int _port=8080)
            :ip(_ip), port(_port)
        {}
        void initServer()
        {
            sock = socket(AF_INET, SOCK_DGRAM, 0);
            std::cout << "sock: " << sock << std::endl;
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = inet_addr(ip.c_str());


            if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
                std::cerr << "bind error!\n" << std::endl;
                exit(1);
            }
        }


        void start()
        {
            char msg[64];
            for(;;){
                msg[0] = '\0';
                struct sockaddr_in end_point;
                socklen_t len = sizeof(end_point);
                ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,0, (struct sockaddr*)&end_point, &len);
                if(s > 0){
                    msg[s] = '\0';
                    std::cout <<"client# " << msg << std::endl;
                    std::string echo_string = msg;
                    echo_string += " [server echo!]";
                    sendto(sock, echo_string.c_str(), echo_string.size(), 0, (struct sockaddr*)&end_point, len);
                }
            }
        }
        ~udpServer()
        {
            close(sock);
        }
};

//服务器端.cc
#include "udpClient.hpp"

int main()
{
    udpClient uc;
    uc.initClient();
    uc.start();

    return 0;
}
[lvhao@VM-0-12-centos lesson9]$ cat udpServer.cc
#include "udpServer.hpp"

int main()
{
    udpServer *up = new udpServer();

    up->initServer();
    up->start();

    delete up;
}



//客户端 .hpp
#pragma once


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


class udpClient{
    private:
        std::string ip;
        int port;
        int sock;
    public:
        udpClient(std::string _ip="127.0.0.1", int _port=8080)
            :ip(_ip), port(_port)
        {}
        void initClient()
        {
            sock = socket(AF_INET, SOCK_DGRAM, 0);
            std::cout << "sock: " << sock << std::endl;
        }


        void start()
        {
            std::string msg;
            struct sockaddr_in peer;
            peer.sin_family = AF_INET;
            peer.sin_port = htons(port);
            peer.sin_addr.s_addr = inet_addr(ip.c_str());


            for(;;){
                std::cout << "Please Enter# ";
                std::cin >> msg;
                if(msg == "quit"){
                    break;
                }

                sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&peer, sizeof(peer));

                char echo[128];
                ssize_t s = recvfrom(sock, echo, sizeof(echo)-1, 0, nullptr, nullptr);
                if(s >0){
                    echo[s] = 0;
                    std::cout << "server# " << echo << std::endl;
                }
            }
        }
        ~udpClient()
        {
            close(sock);
        }
};

//客户端.cc
#include "udpClient.hpp"

int main()
{
    udpClient uc;
    uc.initClient();
    uc.start();

    return 0;
}

//Makefile
.PHONY:all
all:udpClient udpServer

udpClient:udpClient.cc
	g++ -o $@ $^ -std=c++11
udpServer:udpServer.cc
	g++ -o $@ $^

.PHONY:clean
clean:
	rm -f udpClient udpServer

(三)小结

  • 想要删掉错输的信息按住ctrl+backspace。
  • netstat -nlup查看绑定的ip和端口号。
  • 服务器创建:第一步创建了套接字数据结构,如果没有ip和端口号就无法定位,无法定位就没办法通信,第二步需要在创建sockaddr_in数据结构从而填充协议族,在填充端口号,在填充ip地址,进而在进行相关动作的一个绑定。
  • 服务器端的ip和port不能轻易被更改,必须是确定的,众所周知的。http:80,https:443 ssh:22 MySQL:3306。
  • 客户端给别人发消息就必须知道别人的ip和端口号,这就需要创捷结构填入别人的ip和端口号。
  • 127.0.0.1本地环回,通常用来进行网络通信代码的本地测试,一般跑通说明代码在本地环境以及代码基本没有大问题。
  • 服务器绑定ip为0时等价于绑定公网ip,一般不会这么写。
  • 客户端不需要强bind(绑定)

a.你在进行bind的时候,很容易冲突!客户端无法启动!

b.客户端需要唯一性,但是不需要明确必须是哪个端口号。但是需要ip和port(端口)。client udp,recv和cend,系统会自动进行ip和端口号的绑定!

三、基于TCP的相关理解

(一)TCP协议

  • TCP属于传输层的传输控制协议,比较复杂,管的事多,而UDP则较为简单。
  • 传输层协议
  • 有连接
  • 可靠传输
  • 面向字节流

(二)编写单执行流的TCP服务端和客户端

//服务器hpp
#pragma once

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

#define BACKLOG 5
class tcpServer{
    private:
        int port;
        int lsock; //监听套接字
    public:
        tcpServer(int _port)
            :port(_port), lsock(-1)
        {}
        void initServer()
        {
            lsock = socket(AF_INET, SOCK_STREAM, 0);
            if(lsock < 0){
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = htonl(INADDR_ANY);


            if(bind(lsock, (struct sockaddr*)&local, sizeof(local)) < 0){
                std::cerr << "bind error" << std::endl;
                exit(3);
            }


            if(listen(lsock, BACKLOG) < 0){
                std::cerr << "bind error" << std::endl;
                exit(4);
            }
        }
        void service(int sock)
        {
            char buffer[1024];
            while(true){
                //read or write -> ok!
                size_t s = recv(sock, buffer, sizeof(buffer)-1, 0);
                if(s > 0){
                    buffer[s] = 0;
                    std::cout << "client# " << buffer << std::endl;
                    send(sock, buffer, strlen(buffer), 0);
                }
                else if(s == 0){
                    std::cout << "client quit ...." << std::endl;
                    break;
                }
                else {
                    std::cout << "recv client data error..." << std::endl;
                    break;
                }
            }
            close(sock);
        }
        void start()
        {
            sockaddr_in endpoint;
            while(true){
                socklen_t len = sizeof(endpoint);
                int sock = accept(lsock, (struct sockaddr*)&endpoint, &len);
                if(sock < 0){
                    std::cerr << "accept error" << std::endl;
                    continue;
                }
                std::string cli_info = inet_ntoa(endpoint.sin_addr);
                cli_info += ":";
                cli_info += std::to_string(ntohs(endpoint.sin_port));
                std::cout << "get a new link ..." << cli_info << " sock: " << sock <<std::endl;
                service(sock);
            }
        }
        ~tcpServer()
        {}
};

//服务器.cc
#include "tcpServer.hpp"
static void Usage(std::string proc)
{
    std::cout << "Usage: " << std::endl;
    std::cout << '\t' << proc << " port" << std::endl;
}

int main(int argc, char *argv[])
{
    if(argc != 2){
        Usage(argv[0]);
        exit(1);
    }
    tcpServer * tp = new tcpServer(atoi(argv[1]));
    tp->initServer();
    tp->start();
    delete tp;
    return 0;
}

//客户端  .hpp

#pragma  once
#include <iostream>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

class tcpClient{
    private:
        std::string svr_ip;
        int svr_port;
        int sock;
    public:
        tcpClient(std::string _ip="127.0.0.1", int _port = 8080)
            :svr_ip(_ip),svr_port(_port)
        {}
        void initClient()
        {
            sock = socket(AF_INET, SOCK_STREAM, 0);
            if(sock < 0){
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in svr;
            svr.sin_family = AF_INET;
            svr.sin_port = htons(svr_port);
            svr.sin_addr.s_addr = inet_addr(svr_ip.c_str());


            if(connect(sock, (struct sockaddr*)&svr, sizeof(svr)) != 0){
                std::cerr << "connect error" << std::endl;
            }
            //connect success;
        }
        void start()
        {
            char msg[64];
            while(true){
                std::cout << "Please Enter Message# ";
                fflush(stdout);
                size_t s = read(0, msg, sizeof(msg)-1);
                if(s > 0){
                    msg[s-1] = 0;
                    send(sock, msg, strlen(msg), 0);
                    size_t ss = recv(sock, msg, sizeof(msg)-1, 0);
                    if(ss > 0){
                        msg[ss] = 0;
                        std::cout << "server echo # " << msg << std::endl;
                    }
                }
            }
        }
        ~tcpClient()
        {
            close(sock);
        }
};
//客户端  .cc
#include "tcpClient.hpp"

static void Usage(std::string proc)
{
    std::cout << "Usage: \n" << "\t";
    std::cout << proc << " svr_ip svr_port" << std::endl;
}
int main(int argc, char *argv[])
{
    if(argc != 3){
        Usage(argv[0]);
        exit(1);
    }
    tcpClient *tc = new tcpClient(argv[1], atoi(argv[2]));
    tc->initClient();
    tc->start();
    delete tc;
    return 0;
}



FLAG=-std=c++11

.PHONY:all
all:tcpClient tcpServer

tcpClient:tcpClient.cc
	g++ -o $@ $^ $(FLAG) -static
tcpServer:tcpServer.cc
	g++ -o $@ $^ $(FLAG)

.PHONY:clean
clean:
	rm -f tcpClient tcpServer


  (三)编写多进程的TCP服务端和客户端

//服务器 .hpp
#pragma once
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>


#define BACKLOG 5


class tcpServer{
    private:
        int port;
        int lsock; //监听套接字
    public:
        tcpServer(int _port)
            :port(_port), lsock(-1)
        {}
        void initServer()
        {
            //设置信号  为默认忽略,当子进程要退出时发送信号,系统默认回收。
            signal(SIGCHLD, SIG_IGN);    
            lsock = socket(AF_INET, SOCK_STREAM, 0);
            if(lsock < 0){
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = htonl(INADDR_ANY);


            if(bind(lsock, (struct sockaddr*)&local, sizeof(local)) < 0){
                std::cerr << "bind error" << std::endl;
                exit(3);
            }


            if(listen(lsock, BACKLOG) < 0){
                std::cerr << "bind error" << std::endl;
                exit(4);
            }
        }
        void service(int sock)
        {
            char buffer[1024];
            while(true){
                size_t s = recv(sock, buffer, sizeof(buffer)-1, 0);
                if(s > 0){
                    buffer[s] = 0;
                    std::cout << "client# " << buffer << std::endl;


                    send(sock, buffer, strlen(buffer), 0);
                }
                else if(s == 0){
                    std::cout << "client quit ...." << std::endl;
                    break;
                }
                else {
                    std::cout << "recv client data error..." << std::endl;
                    break;
                }
            }
            close(sock);
        }
        void start()
        {
            sockaddr_in endpoint;
            while(true){
                socklen_t len = sizeof(endpoint);
                int sock = accept(lsock, (struct sockaddr*)&endpoint, &len);
                if(sock < 0){
                    std::cerr << "accept error" << std::endl;
                    continue;
                }
                std::string cli_info = inet_ntoa(endpoint.sin_addr);
                cli_info += ":";
                cli_info += std::to_string(ntohs(endpoint.sin_port));


                std::cout << "get a new link ..." << cli_info << " sock: " << sock <<std::endl;


                pid_t id = fork();
                //child
                if(id == 0){
                    close(lsock);
                    service(sock);
                    exit(0);
                }
                close(sock);
            }
        }
        ~tcpServer()
        {}
};

//服务器.cc
#include "tcpServer.hpp"


static void Usage(std::string proc)
{
    std::cout << "Usage: " << std::endl;
    std::cout << '\t' << proc << " port" << std::endl;
}


int main(int argc, char *argv[])
{
    if(argc != 2){
        Usage(argv[0]);
        exit(1);
    }


    tcpServer * tp = new tcpServer(atoi(argv[1]));
    tp->initServer();
    tp->start();


    delete tp;
    return 0;
}
//客户端.hpp
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

class tcpClient{
    private:
        std::string svr_ip;
        int svr_port;
        int sock;
    public:
        tcpClient(std::string _ip="127.0.0.1", int _port = 8080)
            :svr_ip(_ip),svr_port(_port)
        {}
        void initClient()
        {
            sock = socket(AF_INET, SOCK_STREAM, 0);
            if(sock < 0){
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in svr;
            svr.sin_family = AF_INET;
            svr.sin_port = htons(svr_port);
            svr.sin_addr.s_addr = inet_addr(svr_ip.c_str());
            if(connect(sock, (struct sockaddr*)&svr, sizeof(svr)) != 0){
                std::cerr << "connect error" << std::endl;
            }
        }
        void start()
        {
            char msg[64];
            while(true){
                std::cout << "Please Enter Message# ";
                fflush(stdout);
                size_t s = read(0, msg, sizeof(msg)-1);
                if(s > 0){
                    msg[s-1] = 0;
                    send(sock, msg, strlen(msg), 0);
                    size_t ss = recv(sock, msg, sizeof(msg)-1, 0);
                    if(ss > 0){
                        msg[ss] = 0;
                        std::cout << "server echo # " << msg << std::endl;
                    }
                    else if(ss == 0){
                        break;
                    }
                    else{
                        break;
                    }
                }
            }
        }
        ~tcpClient()
        {
            close(sock);
        }
};
//客户端.cc
#include "tcpClient.hpp"
static void Usage(std::string proc)
{
    std::cout << "Usage: \n" << "\t";
    std::cout << proc << " svr_ip svr_port" << std::endl;
}
int main(int argc, char *argv[])
{
    if(argc != 3){
        Usage(argv[0]);
        exit(1);
    }
    tcpClient *tc = new tcpClient(argv[1], atoi(argv[2]));
    tc->initClient();
    tc->start();
    delete tc;
    return 0;
}



(四)编写多线程的TCP服务端和客户端

//服务器.hpp
#pragma once
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>


#define BACKLOG 5


class tcpServer{
    private:
        int port;
        int lsock; //监听套接字
    public:
        tcpServer(int _port)
            :port(_port), lsock(-1)
        {}
        void initServer()
        {
            signal(SIGCHLD, SIG_IGN);
            lsock = socket(AF_INET, SOCK_STREAM, 0);
            if(lsock < 0){
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = htonl(INADDR_ANY);


            if(bind(lsock, (struct sockaddr*)&local, sizeof(local)) < 0){
                std::cerr << "bind error" << std::endl;
                exit(3);
            }


            if(listen(lsock, BACKLOG) < 0){
                std::cerr << "bind error" << std::endl;
                exit(4);
            }
        }
        static void service(int sock)
        {
            char buffer[1024];
            while(true){
                size_t s = recv(sock, buffer, sizeof(buffer)-1, 0);
                if(s > 0){
                    buffer[s] = 0;
                    std::cout << "client# " << buffer << std::endl;


                    send(sock, buffer, strlen(buffer), 0);
                }
                else if(s == 0){
                    std::cout << "client quit ...." << std::endl;
                    break;
                }
                else {
                    std::cout << "recv client data error..." << std::endl;
                    break;
                }
            }
            close(sock);
        }
        static void *serviceRoutine(void *arg)
        {
            pthread_detach(pthread_self());
            std::cout << "create a new thread for IO" << std::endl;
            int *p = (int*)arg;
            int sock = *p;
            service(sock);
            delete p;
        
        }
        void start()
        {
            sockaddr_in endpoint;
            while(true){
                socklen_t len = sizeof(endpoint);
                int sock = accept(lsock, (struct sockaddr*)&endpoint, &len);
                if(sock < 0){
                    std::cerr << "accept error" << std::endl;
                    continue;
                }
                std::string cli_info = inet_ntoa(endpoint.sin_addr);
                cli_info += ":";
                cli_info += std::to_string(ntohs(endpoint.sin_port));


                std::cout << "get a new link ..." << cli_info << " sock: " << sock <<std::endl;


             pthread_t tid;
             int *p = new int(sock);
             pthread_create(&tid, nullptr, serviceRoutine, (void*)p); 
            }
        }
        ~tcpServer()
        {}
};
//服务器.cc
#include "tcpServer.hpp"


static void Usage(std::string proc)
{
    std::cout << "Usage: " << std::endl;
    std::cout << '\t' << proc << " port" << std::endl;
}


int main(int argc, char *argv[])
{
    if(argc != 2){
        Usage(argv[0]);
        exit(1);
    }


    tcpServer * tp = new tcpServer(atoi(argv[1]));
    tp->initServer();
    tp->start();


    delete tp;
    return 0;
}
//客户端.hpp
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>






class tcpClient{
    private:
        std::string svr_ip;
        int svr_port;
        int sock;
    public:
        tcpClient(std::string _ip="127.0.0.1", int _port = 8080)
            :svr_ip(_ip),svr_port(_port)
        {}
        void initClient()
        {
            sock = socket(AF_INET, SOCK_STREAM, 0);
            if(sock < 0){
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in svr;
            svr.sin_family = AF_INET;
            svr.sin_port = htons(svr_port);
            svr.sin_addr.s_addr = inet_addr(svr_ip.c_str());


            if(connect(sock, (struct sockaddr*)&svr, sizeof(svr)) != 0){
                std::cerr << "connect error" << std::endl;
            }
        }
        void start()
        {
            char msg[64];
            while(true){
                std::cout << "Please Enter Message# ";
                fflush(stdout);
                size_t s = read(0, msg, sizeof(msg)-1);
                if(s > 0){
                    msg[s-1] = 0;
                    send(sock, msg, strlen(msg), 0);
                    size_t ss = recv(sock, msg, sizeof(msg)-1, 0);
                    if(ss > 0){
                        msg[ss] = 0;
                        std::cout << "server echo # " << msg << std::endl;
                    }
                    else if(ss == 0){
                        break;
                    }
                    else{
                        break;
                    }
                }
            }
        }
        ~tcpClient()
        {
            close(sock);
        }
};

//客户端.cc
#include "tcpClient.hpp"


void Usage(std::string proc)
{
    std::cout << "Usage: \n" << "\t";
    std::cout << proc << " svr_ip svr_port" << std::endl;
}


int main(int argc, char *argv[])
{
    if(argc != 3){
        Usage(argv[0]);
        exit(1);
    }
    tcpClient *tc = new tcpClient(argv[1], atoi(argv[2]));


    tc->initClient();
    tc->start();


    delete tc;
    return 0;
}

(五)小结

  • 工程上一般很少使用ip,只使用端口号,一般填INADDR_ANY(可以理解代表该机器的全部IP),这个宏表示本地任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,知道与某个客户端建立了连接时才确定下来到底用哪个IP地址。
  • tcp绑定后,必须让tcp设置成监听状态,TCP允许在任何时刻链接我,不连接不能进行发送但是UDP可以,所以UDP叫做无链接。UDP相当于标定了IP和端口号,并没有进行连接他俩。
  • 192.168.1.2.3是字符串风格的四字节 点分十进制方案。inet_ntoa四字节IP转换成点分十进制。inet_addr四字节字符串风格的IP地址转化成四字节网络序列IP。
  • telnet登录一个服务器所需要的命令要进行交互输入ctrl+上尖括号。
  • +static代码只要系统一样,代码则不依赖任何第三方库就可以跑。
  • 客户端和服务器都需要-std=c++11时我们需要FLAG=-std=c++11;  后面直接$(FLAG);
  • sz -E+文件名+rz   就是从linux发送到windows。
  • cp -rf +需要拷贝的文件夹+拷贝成那个名字的文件夹在当前路径拷贝一个文件夹。

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux学习笔记-----网络编程套接字 的相关文章

  • Inotify linux 监视子目录

    是否可以以这种模式监视目录 storage data usernames Download gt storage data Download 我需要监视每个用户的下载文件夹中是否进行了更改 也许我需要创建所有路径的列表 将其放入数组中 并在
  • 如何不断刷新屏幕并实时更新[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想在linux上写一个C程序 不断刷新屏幕并实时更新 例如类似于top终端中的命令 谁能指出我正确的方向 为了保持它跨终端类型的可移
  • 在Linux中断上下文中运行用户线程

    我正在编写一些定制的应用程序 并允许更改 Linux 内核中的中断处理程序代码 我有一个用户线程正在等待中断发生 如果发生中断 那么我要做的第一件事就是执行该用户线程 有什么办法让它发挥作用吗 Thanks 创建一个字符设备 这就是内核所做
  • linux x86 汇编语言 sys_read 调用的第一个参数应为 0 (stdin)

    我正在编写一个简单的汇编程序来从标准输入读取 如 scanf 这是我的代码 section bss num resb 5 section txt global start start mov eax 3 sys read mov ebx 0
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • Composer 安装要求

    我正在尝试将 Composer 安装到 Laravel 项目中 当我做的时候sudo composer install在项目目录中它显示了两个错误 Problem 1 Installation request for simplesoftw
  • Linux 桌面快捷方式和安装图标

    我需要添加什么到我的 spec文件来创建桌面快捷方式并在安装过程中为快捷方式分配一个图标 rpm 如果需要脚本 一个示例将非常有帮助 您在 Linux 下使用 desktop 文件作为图标 图标放置的位置取决于您使用的发行版和桌面环境 由于
  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • 在 Linux 上的 Python 中使用受密码保护的 Excel 工作表

    问题很简单 我每周都会收到一堆受密码保护的 Excel 文件 我必须解析它们并使用 Python 将某些部分写入新文件 我得到了文件的密码 当在 Windows 上完成此操作时 处理起来很简单 我只需导入 win32com 并使用 clie
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 并行运行 make 时出错

    考虑以下制作 all a b a echo a exit 1 b echo b start sleep 1 echo b end 当运行它时make j2我收到以下输出 echo a echo b start a exit 1 b star
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • ansible 重新启动 2.1.1.0 失败

    我一直在尝试创建一个非常简单的 Ansible 剧本 它将重新启动服务器并等待它回来 我过去在 Ansible 1 9 上有一个可以运行的 但我最近升级到 2 1 1 0 并且失败了 我正在重新启动的主机名为 idm IP 为 192 16
  • 在 Mac OS X 上构建 Linux 内核

    我正在做一个修改Linux内核的项目 我有一台桌面 Linux 机器 在上面构建内核没有问题 不过 我要去旅行 我想在途中工作 我只有一台 MacBook 当我尝试构建 Linux 内核时 它抱怨说elf h was not found 我
  • 在 Linux 上更快地分叉大型进程?

    在现代 Linux 上达到与 Linux 相同效果的最快 最好的方法是什么 fork execve combo 从一个大的过程 我的问题是进程分叉大约 500MByte 大 并且一个简单的基准测试只能从进程中实现约 50 个分叉 秒 比较最
  • 创建 jar 文件 - 保留文件权限

    我想知道如何创建一个保留其内容的文件权限的 jar 文件 我将源代码和可执行文件打包在一个 jar 文件中 该文件将在使用前提取 人们应该能够通过运行批处理 shell 脚本文件立即运行示例和演示 然后他们应该能够修改源代码并重新编译所有内
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • Jenkins中找不到环境变量

    我想在詹金斯中设置很多变量 我试过把它们放进去 bashrc bash profile and profile of the jenkins用户 但 Jenkins 在构建发生时找不到它们 唯一有效的方法是将所有环境变量放入Jenkinsf
  • 如何根据 HTTP 请求使用 Python 和 Flask 执行 shell 命令并流输出?

    下列的这个帖子 https stackoverflow com questions 15092961 how to continuously display python output in a webpage 我能够tail f网页的日志

随机推荐

  • Artifactory Maven 使用教程

    Maven 仓库使用 修改 Maven 配置文件 选择左侧 Artifacts 选择自己需要上传的 Maven 仓库 点击Set Me Up 在弹出的设置框中点击 点击下载生成的文件 将生成的文件放到此目录下 或者你自己的 Maven 目录
  • 线性回归模型

    线性回归是最简单的机器学习模型 也是最基础最重要的分析工具 易于实现 本文将将简单讲述线性回归 最小二乘法和梯度下降三种算法 目录 1 线性回归方程 OLS 2 最小二乘法 OLS 3 梯度下降 GD 3 1超参数 的选择 3 2局部最小值
  • Android使用OpenCV来实现bitmap独立设置每个圆角

    Android使用OpenCV来实现bitmap独立设置每个圆角 关于opencv集成请参考我的其他文章 这里方便起见已经封装成java方法供大家调用 代码如下 public static Bitmap drawCircleRadius i
  • 打乱1-100的个数字的顺序

    package test import java util Random public class Test2 public static void swap int a int i int j if a null a length 0 i
  • Weex页面的编写——Weex的学习之路(六)

    通过前几博客我们把weex的内置组件都学习完了 组件的单独使用想必都可以了 那么 这次我们来做weex实际页面的编写 见证一下 一套代码在Android Ios和H5上使用 在weex官网推荐我们使用Weex Studio作为编译器 其实这
  • Unity 3D作业二:离散仿真引擎基础

    前言 中山大学中山大学数据科学与计算机学院3D游戏课程学习记录博客 简答题 1 解释游戏对象 GameObjects 和资源 Assets 的区别与联系 游戏对象 出现在游戏场景中 充当游戏的组件 游戏对象不做任何事情 需要特殊属性才能成为
  • Xcode Executable Not Found

    问题 Xcode编译项目报Executable Not Found的错误 Details Details Executable Not Found Domain DVTMachOErrorDomain Code 5 Recovery Sug
  • Rust 删除排序数组中的重复项

    力扣https leetcode cn com problems remove duplicates from sorted array 参考代码和注释 fn main let mut v Vec
  • Linux下Elasticsearch离线安装

    先去下载离线安装包 我这里是7 10 0 Past Releases of Elastic Stack Software Elastic 上传到 usr local下 解压 tar zxvf elasticsearch 7 10 0 lin
  • 【MATLAB】MATLAB打开后,提示内部崩溃,直接闪退关闭——解决方法

    问题描述 在第一次安装MATLAB软件时 正常使用 过了一段时间后 突然发现在命令行可以正常使用 但运行编译文件里的程序便会报 MathWorks 崩溃的错误 提示MATLAB遇到了内部问题 需要关闭 结果MATLAB自己闪退结束 解决方法
  • MATLAB(6)GUI应用介绍

    目录 GUI编辑器 控件 属性 回调函数 MATLAB常见的控件 普通按钮 切换按钮 可编辑文本 字符获取 字符显示 复选框 单选按钮 弹出式菜单 滑动条 列表框 表 坐标区 附录 各文件共享数据 保存 获取 GUI编辑器 MATLAB的G
  • 【问题记录】05 Host key for [ip] has changed and you have requested strict checking.Host key verification

    1 报错信息如下 为主机ip WARNING REMOTE HOST IDENTIFICATION HAS CHANGED IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY Someo
  • 操作系统实验——互斥与同步

    目录 1 SYSTEM V信号量 1 创建或打开 semget 2 申请或释放 semop 3 设置信号量 semctl 2 POSIX信号量 1 初始化 sem init 2 申请和释放 sem wait 3 销毁 sem destroy
  • 详细记录YOLACT实例分割ncnn实现

    点击上方 AI算法修炼营 选择加星标或 置顶 标题以下 全是干货 整理 公众号 深度学习与计算机视觉 作者 nihui 链接 https zhuanlan zhihu com p 128974102 本文转载自知乎 作者已授权 未经许可请勿
  • 《写给大家看的设计书(第4版)》读书笔记

    文章目录 前言 设计原则 亲密性 对齐 重复 对比 结语 前言 设计类的书籍看过一些 大多分为两类 一类是讲基础的 构图 明暗 色彩等基础理论 还有一类是分享介绍具体案里的 这两类书籍对于大多数并不想真正成为设计师的人来说很多时候并没有什么
  • 位置无关码介绍

    1 基本概念 应用程序必须经过编译 汇编和链接后才变成可执行文件 在链接时 要对所有目标文件进行地址重定位 建立符号引用规则 同时为变量 函数等分配运行地址 当程序执行时 系统必须把代码加载到链接时所指定的地址空间即链接地址 链接地址介绍在
  • 使用C写Python的模块

    使用C写Python的模块 2012 12 21 23 49 更新 邹业盛 概述 引入 Python h 头文件 编写包装函数 处理从 Python 传入的参数 实现逻辑功能 处理 C 中的返回值 注册函数 注册模块 编译 原文发于2010
  • 【开发工具】【make】make 3.82源码编译安装

    摘要 通过下载make 3 82源码 再编译机上安装make 3 82版本 解决make版本过高的问题 1 下载make 3 82 下载地址为 wget ftp ftp gnu org gnu make make 3 82 tar gz 我
  • 全局监控 click事件的四种方式

    本文主要给大家分享如何在全局上去监听 click 点击事件 并做些通用处理或是拦截 使用场景可能就是具体的全局防快速重复点击 或是通用打点分析上报 用户行为监控等 以下将以四种不同的思路和实现方式去监控全局的点击操作 由简单到复杂逐一讲解
  • Linux学习笔记-----网络编程套接字

    目录 一 概念 一 端口号概念 二 套接字概念 三 套接字 socket 编程接口 四 sockaddr结构 五 网络字节序 二 基于UDP的相关理解 一 UDP协议 二 编写简单的UDP服务端和客户端 三 小结 三 基于TCP的相关理解