前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >1-UNIX网络编程-Socket套接字编程简介

1-UNIX网络编程-Socket套接字编程简介

作者头像
zoujunjie202
发布2022-07-27 15:41:08
1.1K0
发布2022-07-27 15:41:08
举报
文章被收录于专栏:zoujunjie202

触发学习UNIX网络编程的动力在于前段时间需要开发一个接入服务,需要考虑比较高的并发处理能力,且尽量少占用的机器资源,选用了JAVA的Netty框架,学习过程产生不少疑问,限于基础知识太薄弱无法理解原理,所以开始关注UNIX编程。

学习资料是这本书,书有砖头那么大,知识点非常多,分几个小章节记录汇总。这个章节作为开篇,记录最基础的API使用指引。

有C语言基础都可以看得懂的Server和Client端代

Server端代码

代码语言:javascript
复制
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define MAXLINE     4096
#define LISTENQ     1024

int main(int argc , char **argv ){
    int                 listenfd, connfd, n;
    char                buff[MAXLINE+1];
    struct sockaddr_in  servaddr;
    // socket
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(13);
    // bind
    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    // listen
    listen(listenfd,LISTENQ);
    for(;;){
        connfd = accept(listenfd,NULL,NULL);
        while( ( n= read(connfd,buff,MAXLINE)) > 0 ){
            printf("receive message from client. message = %s",buff);
            write(connfd,buff,strlen(buff));
            bzero(&buff,sizeof(buff));
        }
        close(connfd);
    }
}

Client端代码

代码语言:javascript
复制
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAXLINE     4096
#define LISTENQ     1024

int
main(int argc , char **argv ){
    int                 sockfd, n;
    char                sendline[MAXLINE+1] ,recvline[MAXLINE+1];
    struct sockaddr_in  servaddr;
    // socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13);
    inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
    // connect
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    
    while( fgets(sendline,MAXLINE,stdin) != NULL ){
        write(sockfd,sendline,strlen(sendline));
        bzero(&recvline,sizeof(recvline));
        if( (n = read(sockfd,recvline,MAXLINE) ) > 0 ){
            recvline[n] = 0 ;
            printf("receive message from server. message = %s",recvline);
            // fputs(recvline,stdout);
        }
        bzero(&sendline,sizeof(sendline));
    }
    close(sockfd);
    exit(0);
}

程序运行示例

这是一个简单的回射程序,不管客户端发送什么消息,服务器端接受到消息之后原样返回给客户端。不包含任何错误判断和错误处理。

关键函数注解

代码语言:javascript
复制
1、socket函数
int socket( int family , int type , int protocol );
    创建一个套接字文件,返回套接字文件描述符
[family]
    指定协议簇 : AF_INET(IPv4) AF_INET6(IPv6) 
    AF_LOCAL(UNIX协议) AF_ROUTE(路由套接字) AF_KEY(秘钥套接字)
[type]
    指定套接字类型 : SOCK_STREAM(字节流套接字)、
    SOCK_DGRAM(数据报套接字)、SOCK_SEQPACKET(有序分组套接字)、
    ROCK_RAW(原始套接字)
[protocol]
     指定协议类型:IPPROTO_TCP(TCP传输协议)、
     IPPROTO_UDP(UDP传输协议)、IPPROTO_SCTP(STCP传输协议),
     设置为0可以表示选择给定family和type组合的系统默认值。通常设置为0。
代码语言:javascript
复制
2、bind函数
int bind(int sockfd , const struct sockaddr *myaddr , 
socklen_t addrlen);
    把一个本地协议地址赋予一个套接字
[sockfd]
    socket函数返回的套接字描述符
[myaddr]
    是指向本地IP地址的通用套接字结构
[addrlen]
    特定套接字结构的长度(IPv4、IPv6、Unix域、数据链路、存储等)
代码语言:javascript
复制
3、listen函数
int listen( int sockfd , int backlog );
    把一个本地协议地址赋予一个套接字,把套件字变更为被动连接。
[sockfd]
    socket指示内核接受指向该套接字的连接请求。
[backlog]
    未完成三次握手的请求 + 已完成三次握手的请求总和。是一个大约值。
代码语言:javascript
复制
4、accept函数
int accept( int sockfd , struct sockaddr *cliaddr , 
scoklen_t *addrlen );
    从已完成连接队列队头返回下一个已完成连接,如果丢列为空,
    进程阻塞进入睡眠。
[sockfd]
    socket等待接受连接的侦听套接字。
[cliaddr]
    客户端协议地址。如果不关注客户端的地址,可以设置为NULL。
[addrlen]
    客户端协议地址的端口号。如果不关注,可以设置为NULL。
代码语言:javascript
复制
5、connect函数
int connect( int sockfd , const struct sockaddr * servaddr , 
socklen_t addrlen );
     TCP客户端发起跟服务器的连接。
[sockfd]
    由socket函数创建的套接字连接
[servaddr]
    包含服务器IP地址和端口号的套接字地址结构
[addrlen]
     套接字地址结构的大小。
代码语言:javascript
复制
bzero       字节操纵函数,用于把目的结构体中指定数目的字节置为0
            类似于memset函数,但是比memset少一个容易出BUG的参数
            在C语言里,对一块刚申请的内存先清零再使用是必须的
htonl\htons 字节排序函数,
            htonl是对32位的IPv4地址做转换
            htons是对16为的端口号做转换
            由机器字节序转变为网络字节序,网际协议使用大端字节序来表示
            字符,而机器则是不同操作系统使用不同的字节序
read        从连接套接字中读取指定长度的内容
write       往连接套接字中写取指定长度的内容
inet_pton   把字符串格式的IP地址,转成相应协议族的数值格式
            另外一个配套的函数是inet_ntop,作用相反
fgets       函数,从标准输入中读取指定长度字符串,有点像scanf

基础知识补齐

1、Socket在OSI(开放系统互联)模型——7层网络模型中的位置

Socket就像一个插头,联通应用层中的应用与网络设备,应用要提供网络服务,或者需要网络服务都得通过Socket的API进行。

2、Socket API的数据流

下周文章提纲

1、C语言错误处理

2、项目文件组织与编写Makefile

3、完成server和client中其他函数的包裹

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 zoujunjie202 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档