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);

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: %s
", 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: %s
", szBuffer);
    //关闭套接字
    closesocket(sock);
    //终止使用 DLL
    WSACleanup();
    system("pause");
    return 0;
}
nbytes
原文地址:https://www.cnblogs.com/qifeng1024/p/12692311.html