我是靠谱客的博主 乐观手链,最近开发中收集的这篇文章主要介绍网络socket的编写和一些函数的运用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

    • 客户端client
        • socket函数
        • 定义结构体
        • connect函数
        • write函数
        • read函数
    • 服务器server
        • socket函数调用
        • 结构体servaddr
        • bind函数
        • listen函数
        • accept函数
        • 读写
            • read函数
            • write函数

客户端client

socket函数

头文件:
#include <sys/types.h>
#include <sys/socket.h>

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

参数domain:
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_INET(IPV4)

参数type:
SOCK_STREAM:TCP协议
SOCK_DGRAM:UDP协议

参数protocol:
会根据参数type自动选择,默认为0。

定义结构体

定义结构体servaddr以确定目的IP和端口

 struct sockaddr_in  servaddr; 

如需定义ipv6则把sockaddr_in换成sockadddr_in6
在这里插入图片描述

在这里插入图片描述

之后利用定义的结构体确定目的IP和目的端口:

memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;        //确定ipv4主机字节序
    servaddr.sin_port = htons(port);      //用htons函数把端口号变为网络字节序
    inet_aton(sockip, &servaddr.sin_addr);//调用地址转换函数确定IP地址

connect函数

调用connect函数用以连接服务器

头文件:
#include <sys/types.h>
#include <sys/socket.h>

函数原型:
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

前面已经定义好带有端口号和IP的结构体servaddr,故只需将其带入connect函数中即可

参数const struct sockaddr *addr:
*addr型,填上servaddr,由于类型不匹配,需要强制类型转换,具体代码如下:

    rv = connect(sockfd, (struct sockaddr *)&servaddr,
sizeof(servaddr));//调用可以连接服务器的connect函数
    if( rv < 0 )
    {
        printf("Connect to server[%s:%d] failure:%sn", 
                 sockip, port, strerror(errno));//如果调用失败打印出错
        return -2;
    }
    printf("Connect to server[%s:%d] successfullyn", 
                 sockip, port);          //打印成功

write函数

write函数用以给服务器发送内容

头文件:
#include <unistd.h>

函数原型:
ssize_t write(int fd, const void *buf, size_t count);

参数fd直接带入sockfd,
参数*buf:给服务器发送的信息内容;
参数count:缓冲区大小
具体代码如下:

        rv = write(sockfd, "Hello world", strlen("Hello world")); //往服务器写内容,
        if( rv < 0 )
        {
            printf("Write to server by sockfd[%d] failure:%sn", 
                        sockfd, strerror(errno));//打印出错原因,
            break;
        }

write函数和read函数需要包含在while(1)循环内

read函数

read函数用以接收读取服务器发送过来的内容。

头文件:
#include <unistd.h>

函数原型:
ssize_t read(int fd, void *buf, size_t count);

参数fd:直接带入sockfd
参数*buf:从服务器接收到的信息内容
参数count:缓冲区大小
具体代码如下:

        rv = read(sockfd, buf, sizeof(buf));
        if( rv < 0 )
        {
            printf("Read data from server by sockfd[%d] failure:%sn",
                     sockfd, strerror(errno));//调用失败,打印出错原因
            break;
        }
        else if( rv == 0 )
        {
            printf("Socket[%d] get disconnectedn", 
                     sockfd);
            break;
        }
        else if( rv > 0 )
        {
            printf("Read %d bytes data from server :%sn", 
                     rv, buf);//调用成功
        }

write函数和read函数需要包含在while(1)循环内

值得注意的是,一般来说客户端先调用write函数,后调用read函数,而服务器相反,这样可以避免两边冲突,造成读取失败,下面会介绍服务器server代码的编写

服务器server

socket函数调用

与客户端类似,详见上文

结构体servaddr

端口号和协议与客户端类似,但由于服务器端不需要连接目的IP,而是需要容纳各个服务器的连接,因此在确定IP部分有区别于客户端代码,具体如下

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;         //确定 IPv4主机字节序
    servaddr.sin_port = htons(port);       //用 htons函数把端口号变为网络字节序
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
          //确定服务器IP地址,htonl函数把客户端IP号变为网络字节序

bind函数

与客户端的connect函数类似,是用来连接客户端的函数

头文件:
#include <sys/types.h>
#include <sys/socket.h>

函数原型:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
将servaddr带入其中即可。
具体代码如下:

    rv = bind(sockfd, (struct sockaddr *)&servaddr, 
                  sizeof(servaddr));//调用bind函数
    if( rv < 0 )
    {
        printf("Sockfd[%d] bind on port[%d] failure:%sn", 
                  sockfd, port, strerror(errno));     //打印出错
        return -2;
    }
    printf("Sockfd[%d] bind on port[%d] successfullyn", 
                  sockfd, port);          //打印成功

listen函数

调用listen函数监听端口,
头文件:
#include <sys/types.h>
#include <sys/socket.h>

函数原型:
int listen(int sockfd, int backlog);
参数backlog是指同时连接服务器的客户端个数,一般我们设置为13,
具体代码如下:


    listen(sockfd, 13);
    printf("Start to listen on port[%d]n", port);
         //如果调用成功,则打印监听的端口

accept函数

accept函数用来处理与客户端的连接

头文件:
#include <sys/types.h>
#include <sys/socket.h>

函数原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数struct sockaddr *addr:需要重新定义一个结构体用来接收客户端的IP和端口信息

参数addrlen:需要定义一个socklen_t类型的值,
具体代码如下:

while1{
    struct sockaddr_in  cliaddr;  //定义接收客户端信息的结构体
    socklen_t           len;

    clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
         //定义一个clifd,来返回accept值,
        if( clifd < 0)
        {
            printf("Accept new client failure:%sn",
                   strerror(errno));//函数调用错误,打印错误原因
            continue;
            return -3;
        }
    printf("Accept new client[%s:%d] successfullyn",
          inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
          //打印出接收到的客户端IP地址和端口号,
}

读写

注意:因为服务器要与客户端进行通信,故read函数和write函数对象都变成了clifd客户端,

read函数

服务器先调用read函数,再调用write函数,代码如下

 rv = read(clifd, buf, sizeof(buf));
 if( rv < 0 )
 {
        printf("Read data from server by sockfd[%d] failure:%sn", 
                    sockfd, strerror(errno));//打印出错
        close(clifd);
        continue;
}
  else if( rv == 0 )
{
        printf("Socket[%d] get disconnectedn", sockfd);
        close(clifd);
        continue;
}
else if( rv > 0 )
{
        printf("Read %d bytes data from server :%sn", rv, buf);
}

read代码是包含在accept函数之前的while(1)循环内的

write函数

具体用法见上文,代码如下

       rv = write(clifd, MSG_FD, strlen(MSG_FD));                         //往服务器写内容(MSG_FD)
        if( rv < 0 )
        {
            printf("Write to server by sockfd[%d] failure:%sn", 
                            sockfd, strerror(errno));//打印出错
            close(clifd);
            continue;
        }

write代码是包含在accept函数之前的while(1)循环内的

最后

以上就是乐观手链为你收集整理的网络socket的编写和一些函数的运用的全部内容,希望文章能够帮你解决网络socket的编写和一些函数的运用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部