服务端

步骤:

  1. socket()获取listenfd
  2. bind()绑定listenfd到给定端口
  3. listen()监听绑定的端口
  4. accept()建立连接

accept之后就建立了通信了,使用send()、recv()发送和接收数据

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cerrno>
#include<cstring>

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

using namespace std;
int main()
{
    cout << "This is server" << endl;
    //socket(),获取listenfd
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1)
    {
        cout << "Error: socket" << endl;
        return 0;
    }

    //bind(),绑定端口
    struct sockaddr_in addr;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8000);
    if (bind(listenfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
    {
        cout << "Error: bind" << endl;
        return 0;
    }

    //listen(),监听端口
    if (listen(listenfd, 5) == -1)
    {
        cout << "Error: listen" << endl;
        return 0;
    }

    //accept(),建立连接
    int conn;
    char clientIP[INET_ADDRSTRLEN] = "";
    struct sockaddr_in clientAddr;
    socklen_t clientAddrLen = sizeof(clientAddr);

    while (true)
    {
        cout << "...listening" << endl;
        conn = accept(listenfd, (struct sockaddr*)&clientAddr, &clientAddrLen);//获取clientAddr
        if (conn < 0)
        {
            cout << "Error: accept" << endl;
            continue;
        }

        inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);
        cout << "...connect " << clientIP << ":" << ntohs(clientAddr.sin_port) << endl;
        send(conn, (char*)"Welcome to socket...\\n", 21, 0);

        char buf[255];
        while(true)
        {
            memset(buf, 0, sizeof(buf));
            int len = recv(conn, buf, sizeof(buf), 0);
            buf[len-1] = '\\0';

            if (strcmp(buf, "exit") == 0)
            {
                cout << "...disconnect " << clientIP << ":" << ntohs(clientAddr.sin_port) << endl;
                break;
            }

            cout << buf << endl;
            send(conn, buf, len, 0);
        }

        close(conn);
    }

    close(listenfd);
    return 0;

}

客户端

步骤

  1. socket()得到client
  2. connect()连接服务端

然后就可以使用send()、recv()发送和接收消息

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cerrno>

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

using namespace std;
int main()
{
    cout << "This is client" << endl;
    //socket
    int client = socket(AF_INET, SOCK_STREAM, 0);
    if (client == -1)
    {
        fprintf(stderr, "Error: socket\\n");
        return -1;
    }

    //connect
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8000);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    if (connect(client, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0)
    {
        fprintf(stderr, "Error: connect\\n");
        return -1;
    }
   
    cout << "...connect" << endl;
    char data[255];
    char buf[255];
    while(true)
    {
        cin >> data;
        send(client, data, strlen(data), 0);
        if (strcmp(data, "exit") == 0)
        {
            cout << "...diaconnect" << endl;
            break;
        }
        memset(buf, 0, sizeof(buf));
        int len = recv(client, buf, sizeof(buf), 0);
        buf[len] = '\\0';
        cout << buf << endl;
    }

    close(client);
    return 0;
    
}

主要函数

socket()

原型:

int socket(int domain, int type, int protocol);

功能:创建一个socket描述符(int 类型)

domain:指定协议族

协议族指定了socket的地址类型

常见的协议族:AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE

对于TCP/IP协议族,应设置AF_INET