recv()和send()函数

本文提供了一段简易的TCP服务器及客户端代码示例,使用WinSock2进行网络通信。服务器监听6000端口并接收客户端消息,同时向客户端发送响应。客户端连接服务器并接收服务器的消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结论是实验得来,没有很严谨的查阅资料,注意recv()函数后面的注释就好
这是简单的服务器端代码

#include <WinSock2.h>
#include <stdio.h>
#pragma comment (lib,"ws2_32.lib")

void main()
{
    //用WSAStartup初始化套接字,分配网络资源。即网络层以下部分资源
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(1, 1);//WORD是16位无符号整形,详见WINDOWS常见数据类型,此处用于指定初始化的版本号
    int err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0)
    {
        return;//初始化不成成功
    }
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)//若初始化的版本号不对
    {
        WSACleanup();
        return;
    }

    //创建套接字,套接字需要手动关闭
    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);//此处第一、第三个参数是固定的,第二个参数是TCP的写法,UDP是SOCK_DGRAM
    if (INVALID_SOCKET == sockSrv)//这种写法比较容易发现==写错的情况
    {
        WSACleanup();
        return;
    }

    //绑定到6000端口

    SOCKADDR_IN addrSrv;//此处是TCP/IP必须使用的数据类型
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//此处指定服务器监听的网卡,此参数下监听所有网卡的所有地址,htonl用于把一个数变成一个网址
    addrSrv.sin_port = htons(6000);//绑定端口6000
    addrSrv.sin_family = AF_INET;//TCP/IP

    err = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    if (0 != err)
    {
        WSACleanup();
        return;
    }

    //监听客户请求
    listen(sockSrv, SOMAXCONN);//最大监听的个数

    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);
    while (1)
    {
        //接收客户端请求,得到客户端信息,是一个阻塞函数
        SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
        //向客户端发数据
        char sendBuf[100];
        sprintf(sendBuf, "im 网管,你是%s", inet_ntoa(addrClient.sin_addr)); 
        send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);//第二个参数是要发送的数据,第三个参数是此套接字缓冲区的大小

        //接收数据
        char recvBuf[100];
        int nRecv = recv(sockConn, recvBuf, 100, 0);//返回值代表接收到的字符长度,接收到的字符长度应是对方套接字的缓冲区那么大,也就是说,send一次就会send  client的套接字里缓冲区的所有内容,
        printf("%s\n", recvBuf);
        //关闭客户端连接
        closesocket(sockConn);

    }

    //关闭服务器连接
    closesocket(sockSrv);

    WSACleanup();

}

下面是简单的客户端代码

#include <WinSock2.h>
#include <stdio.h>
#pragma comment (lib,"ws2_32.lib")

void main()
{
    WSADATA wsaData;
    int err = WSAStartup(0x0101, &wsaData);
    if (err != 0)
        return;


    SOCKET sockConn = socket(AF_INET, SOCK_STREAM, 0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_family = AF_INET;
    connect(sockConn, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    char recvBuf[100];
    int nRecv = recv(sockConn, recvBuf, 100, 0);
    recvBuf[nRecv] = '\0';

    printf("%s\n", recvBuf);

    send(sockConn, "hello there", 100,0);
    closesocket(sockConn);
    WSACleanup();
}
好的,以下是一个简单的一对一 Socket 客户端服务器程序,它能够解决 recv send 函数的阻塞问题,让程序同时进行收发通信: 服务器端代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_addr, clnt_addr; socklen_t clnt_addr_size; char message[BUF_SIZE]; if(argc!=2) { printf("Usage: %s <port>\n", argv[0]); exit(1); } serv_sock=socket(PF_INET, SOCK_STREAM, 0); if(serv_sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); serv_addr.sin_port=htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1) error_handling("bind() error"); if(listen(serv_sock, 5)==-1) error_handling("listen() error"); clnt_addr_size=sizeof(clnt_addr); clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr,&clnt_addr_size); if(clnt_sock==-1) error_handling("accept() error"); while(1) { memset(message, 0, BUF_SIZE); /* 接收数据 */ if(recv(clnt_sock, message, BUF_SIZE, MSG_DONTWAIT) > 0) printf("Client: %s", message); /* 发送数据 */ fgets(message, BUF_SIZE, stdin); if(send(clnt_sock, message, strlen(message), 0) == -1) error_handling("send() error"); } close(clnt_sock); close(serv_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } ``` 客户端代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int sock; struct sockaddr_in serv_addr; char message[BUF_SIZE]; if(argc!=3) { printf("Usage: %s <IP> <port>\n", argv[0]); exit(1); } sock=socket(PF_INET, SOCK_STREAM, 0); if(sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr(argv[1]); serv_addr.sin_port=htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1) error_handling("connect() error"); while(1) { memset(message, 0, BUF_SIZE); /* 发送数据 */ fgets(message, BUF_SIZE, stdin); if(send(sock, message, strlen(message), 0) == -1) error_handling("send() error"); /* 接收数据 */ if(recv(sock, message, BUF_SIZE, MSG_DONTWAIT) > 0) printf("Server: %s", message); } close(sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } ``` 在上述代码中,我们使用了 MSG_DONTWAIT 标志来设置 recv send 函数为非阻塞模式,这样就可以让程序同时进行收发通信了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值