c++的socket编程 tcp

首先看一下要用到的一些函数

1、创建套接字 socket()

#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain:       Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
       AF_IPX              IPX - Novell protocols
       AF_NETLINK          Kernel user interface device     netlink(7)
       AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
       AF_AX25             Amateur radio AX.25 protocol
       AF_ATMPVC           Access to raw ATM PVCs
       AF_APPLETALK        AppleTalk                        ddp(7)
       AF_PACKET           Low level packet interface       packet(7)
       AF_ALG              Interface to kernel crypto API
type: 连接类型       SOCK_STREAM     Provides  sequenced,  reliable,  two-way,  connection-
                       based  byte streams.  An out-of-band data transmission
                       mechanism may be supported.

       SOCK_DGRAM      Supports datagrams  (connectionless,  unreliable  mes‐
                       sages of a fixed maximum length).

       SOCK_SEQPACKET  Provides  a  sequenced,  reliable, two-way connection-
                       based data transmission path for  datagrams  of  fixed
                       maximum  length;  a  consumer  is  required to read an
                       entire packet with each input system call.

       SOCK_RAW        Provides raw network protocol access.

       SOCK_RDM        Provides a reliable datagram layer that does not guar‐
                       antee ordering.

       SOCK_PACKET     Obsolete  and  should not be used in new programs; see
                       packet(7).

protocol 协议类型

socket编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW),前两者较常用。基于TCP的socket编程是流式套接字。

2、将socket绑定到地址 bind()

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

sockfd 是在上个函数socket()中获得的文件描述符

addr 结构体类型指针 指向地址

struct sockaddr {
               sa_family_t sa_family;
               char        sa_data[14];
           }

addrlen 长度,是前面那个参数 addr 的长度,一般用sizeof求得

struct sockaddr_in {

  short int sin_family; /* 通信类型 */

  unsigned short int sin_port; /* 端口 */

  struct in_addr sin_addr; /* Internet 地址 */

  unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/

};
struct in_addr {
    in_addr_t s_addr;
};

这里使用sockaddr_in 结构体 传参的时候在强制转换为 sockaddr 结构体

sockaddr_in 是专门用来保存ipv4的结构体 保存ipv6要用 sockaddr_in6

sin_port 用htons()函数 将主机字节序转化为网络字节序

3、监听模式等待请求 linsten()

int listen(int sockfd, int backlog);
sockfd   文件描述符
backlog  等待连接队列的最大长度

4、向服务器发出连接请求 connect()

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd    文件描述符addr     结构体类型指针 指向服务器地址
addrlen   结构体长度

5、服务器接收客户端的连接 accpet()

int accept(int socket,sockaddr * fromaddr,int * addrlen);
socket    文件描述符fromaddr   客户端地址信息
addrlen    地址结构体长度

6、发送数据函数 send()

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

sockfd 文件描述符

*buf 发送的数据

len 发送数据长度

flags 0

7、接收数据函数 recv()

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

sockfd 文件描述符

*buf 接收的数据

len 接收数据长度

flags 0

8、数据的读写 readI() write()

ssize_t read(int fd, void *buf, size_t nbytes);
ssize_t write(int fd, const void *buf, size_t nbytes);

fd 文件描述符

buf 读写的数据存放指针

nbytes 写入读出的数据字节数

9、关闭套接字 closesocket()

int closesocket(int socket);

c++的socket编程 tcp

linux:

服务器:

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

int main(){
    //创建套接字
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //将套接字和IP、端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    //进入监听状态,等待用户发起请求
    listen(serv_sock, 20);

    //接收客户端请求
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_size = sizeof(clnt_addr);
    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

    //向客户端发送数据
    char str[] = "hello world";
    write(clnt_sock, str, sizeof(str));

    //关闭套接字
    close(clnt_sock);
    close(serv_sock);

    return 0;
}

客户端:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main(){
    //创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    //向服务器(特定的IP和端口)发起请求
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    //读取服务器传回的数据
    char buffer[40];
    read(sock, buffer, sizeof(buffer)-1);

    printf("Message form server: %sn", buffer);

    //关闭套接字
    close(sock);
    return 0;
}

windows:

服务器:

#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll
int main(){
    //初始化 DLL
    WSADATA wsaData;
    WSAStartup( MAKEWORD(2, 2), &wsaData);
    //创建套接字
    SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    //绑定套接字
    sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
    sockAddr.sin_family = PF_INET;  //使用IPv4地址
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    sockAddr.sin_port = htons(1234);  //端口
    bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
    //进入监听状态
    listen(servSock, 20);
    //接收客户端请求
    SOCKADDR clntAddr;
    int nSize = sizeof(SOCKADDR);
    SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
    //向客户端发送数据
    char *str = "Hello World!";
    send(clntSock, str, strlen(str)+sizeof(char), NULL);
    //关闭套接字
    closesocket(clntSock);
    closesocket(servSock);
    //终止 DLL 的使用
    WSACleanup();
    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
int main(){
    //初始化DLL
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    //创建套接字
    SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    //向服务器发起请求
    sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
    sockAddr.sin_family = PF_INET;
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sockAddr.sin_port = htons(1234);
    connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
    //接收服务器传回的数据
    char szBuffer[MAXBYTE] = {0};
    recv(sock, szBuffer, MAXBYTE, NULL);
    //输出接收到的数据
    printf("Message form server: %sn", szBuffer);
    //关闭套接字
    closesocket(sock);
    //终止使用 DLL
    WSACleanup();
    system("pause");
    return 0;
}
nbytes

原文链接: https://www.cnblogs.com/qifeng1024/p/12692311.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/195838

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午7:05
下一篇 2023年2月12日 下午7:05

相关推荐