socket编程

文章参考socket教程及《Linux高性能服务器编程》

服务器端

1. 创建socket

采用int socket(int domain, int type, int protocal)函数创建一个套接字;
其中第一个参数domain指定协议族(IPv4/IPv6);
第二个参数type指定服务类型(SOCK_STREAM/SOCK_UGRAM分别对应TCP和UDP);
第三个参数一般默认为0。

#include <stdio.h>
#include <sys/socket.h>

int main()
{
	// IPv4/TCP协议的socket
    int server_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("socket create error");
    }

    printf("socket is %d\n", server_socket);

    return 0;
}

2. 命名socket

在步骤1中仅仅创建了基于IPv4及TCP协议的socket,但并没有指定该socket的地址,也即没有命名。这里采用int bind(int sockfd, const stuct sockaddr *my_addr, socklen_t addrlen)函数来给1中创建的socket绑定一个socket地址;
其中第一个参数sockfd表示socket文件的描述符,也即步骤1中返回的server_socket;
第二个参数表示socket所要绑定的地址,是一个结构体;
第三个参数表示socket地址的长度,也即sizeof(my_addr)。

#include <stdio.h>
#include <stdlib.h>      // exit
#include <string.h>
#include <arpa/inet.h>   // sockaddr_in
#include <sys/socket.h>

int main(int argc, char *argv[])
{
    const char *server_ip = "127.0.0.1"; // IP地址字符串
    int server_port = 0x1234; // 端口号

    int server_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("socket create error");
        exit(1);
    }
    printf("socket is %d\n", server_socket);

    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET; // IPv4
    address.sin_port = htons(server_port); // 服务器端口号,转换为网络序
    address.sin_addr.s_addr = inet_addr(server_ip); 

	// 绑定server_socket到address上
    if (bind(server_socket, (struct sockaddr*)&address, sizeof(address)) == -1) {
        perror("bind error");
        exit(1);
    }
    printf("bind ok\n");

    return 0;
}

3. 服务器监听socket

创建完socket并绑定地址后,socket进入监听状态,使用int listen(int sockfd, int backlog)函数创建一个监听队列以存放待处理的客户连接,将套接字sockfd指定为被监听的socket;
其中第一个参数sockfd为socket文件描述符;
第二个参数表示内核监听队列的最大长度;
成功返回0,失败返回-1。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>   // sockaddr_in
#include <sys/socket.h>

int main()
{
    const char *server_ip = "127.0.0.1"; // IP地址字符串
    int server_port = 0x1234; // 端口号

    int server_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("socket create error");
        exit(1);
    }
    printf("socket is %d\n", server_socket);

    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET; // IPv4
    address.sin_port = htons(server_port); // 服务器端口号,转换为网络序
    address.sin_addr.s_addr = inet_addr(server_ip); 

	// 绑定server_socket到address上
    if (bind(server_socket, (struct sockaddr*)&address, sizeof(address)) == -1) {
        perror("bind error");
        exit(1);
    }
    printf("bind ok\n");

	// 监听server_socket
    if (listen(server_socket, 5) == -1) {
        perror("listen error");
        exit(1);
    }
    printf("listen ok\n");

    return 0;
}

4. 接受连接

当服务器端socket创建完成后,就可以接受来自客户端的连接请求,调用int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)函数;
第一个参数sockfd表示listen指定的监听socket;
第二个参数addr表示客户端的地址;
第三个参数addrlen表示客户端地址的长度;
成功返回一个新的连接socket,该socket唯一标示了接受的新连接,后续双方可以利用已连接套接字进行通信;失败返回-1。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>   // sockaddr_in
#include <sys/socket.h>

int main()
{
    const char *server_ip = "127.0.0.1"; // IP地址字符串
    int server_port = 0x1234; // 端口号

    int server_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("socket create error");
        exit(1);
    }
    printf("socket is %d\n", server_socket);

    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET; // IPv4
    address.sin_port = htons(server_port); // 服务器端口号,转换为网络序
    address.sin_addr.s_addr = inet_addr(server_ip); 

	// 绑定server_socket到address上
    if (bind(server_socket, (struct sockaddr*)&address, sizeof(address)) == -1) {
        perror("bind error");
        exit(1);
    }
    printf("bind ok\n");

	// 监听server_socket
    if (listen(server_socket, 5) == -1) {
        perror("listen error");
        exit(1);
    }
    printf("listen ok\n");

	// 客户机地址
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);

    printf("等待连接中...\n");
    int connfd = accept(server_socket, (struct sockaddr*)&client_addr, 			&client_addr_len);

    if (connfd == -1) {
        perror("accept error");
        exit(1);
    }
    printf("accept ok\n");

    return 0;
}

客户端

建立连接

当服务器端做好接受连接的准备之后,客户端就可以主动请求连接了,这里采用int connect(int sockfd, const struct sockaddr *server_addr, socklen_t *addrlen)函数;
第一个参数sockfd表示socket文件描述符;
第二个参数server_addr表示服务器端的地址;
第三个参数addrlen表示服务器端地址长度;
成功返回0,客户端利用connect函数连接服务端,如果连接成功后,其第一个参数sockfd就唯一标示这个连接;失败返回-1。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值