Socket常用函数及简单实现C/S模型

目录

socket模型创建流程

socket函数

服务器端函数

bind函数

listen函数

accept函数

客户端函数

connect函数

其他函数

read函数

write函数

C/S模型实现

socket实现server端

socket实现client端


socket模型创建流程

注:bind()绑定ip+port
       listen():设置监听上限,同时建立连接的上限数
       accpet():阻塞监听客户端连接
       connect():客户端绑定ip+port

socket函数

创建一个套接字

#include <sys/socket.h>
/*
domain: AF_INET、AF_INET6、AF_UNIX
type: SOCK_STREAM(流式协议)、SOCK_DGRAM (报式协议)
protocol:0(流式协议:TCP、报式协议:UDP)
返回值:成功:新套接字所对应文件描述符
       失败:-1,error
*/
int socket(int domain,int type,int protocol);

服务器端函数

bind函数

给socket绑定一个地址结构(ip+port)

#include <sys/types.h>         
#include <sys/socket.h>
/*
sockfd:socket函数返回值
addr:(struct sockaddr*)&addr sockaddr结构体
addrlen:sizeof(addr)地址结构的大小
返回值:
成功:0
失败:-1 error
*/
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

listen函数

设置同时与服务器建立连接的上限数。(同时进行3次握手的客户端数量)

#include <sys/types.h>         
#include <sys/socket.h>
/*
sockfd:socket函数返回值
backlog:上限数值,最大值:128
返回值:
成功:0
失败:-1 error
*/
int listen(int sockfd, int backlog);

accept函数

阻塞等待客户建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符。

#include <sys/types.h>      
#include <sys/socket.h>
/*
sockfd:socket函数返回值
addr:传出参数。成功与服务器建立连接的那个客户端的地址结构(ip+port)

socklen_t clit_addr_len = sizeof(addr);
addrlen:传入传出:&clit_addr_len
入:addr的大小。出:客户端addr的实际大小

返回值:
成功:能与服务器进行数据通信的socket对应的文件描述
失败:-1,errno
*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);  

客户端函数

connect函数

使用现有的socket与服务器建立连接

#include <sys/types.h>          
#include <sys/socket.h>
/*
sockfd:socket函数返回值
addr:传入参数。服务器的地址结构  
socklen_t clit_addr_len = sizeof(addr);
addrlen:服务器地址长度
返回值:
成功:能与服务器进行数据通信的socket对应的文件描述
失败:-1 errno
*/
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

 如果不使用bind绑定客户端地址结构,采用“隐式绑定”,系统自动分配ip+port

其他函数

read函数

#include <unistd.h>
/*
fd:        文件描述符(文件名或文件路径)
buf:      要写入文件中数据的内存地址
count:  从 buf 写入文件的数据字节数
*/
ssize_t read(int fd, void *buf, size_t count);

注意:当返回值>0时,实际读到的字节数
       
=0时,socket中,表示对端关闭。close()
       =-1时,
       若errno == EINTR  被异常中断,需要重启
       若errno == EAGIN 或 EWOULDBLOCK以非阻塞方式读数据,但是没有数据。需要,再次读
       若errno == ECONNRESET 说明连接被重置

write函数

#include <unistd.h>
/*
fd:        文件描述符(文件名或文件路径)
buf:      要写入文件中数据的内存地址
count:  从 buf 写入文件的数据字节数
*/
ssize_t write(int fd, const void *buf, size_t count);

C/S模型实现

socket实现server端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>

#define SERV_PORT 9527

void sys_err(const char* str){
        perror(str);
        exit(1);
}


int main(int argc,char* argv[]) {

        int ret;
        char buf[BUFSIZ],client_IP[1024];

        struct sockaddr_in serv_addr,clit_addr;
        socklen_t clit_addr_len;

        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(SERV_PORT);
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

        int lfd = socket(AF_INET, SOCK_STREAM, 0 );
        if(lfd == -1){
                sys_err("socket error");
        }

        bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

        listen(lfd,128);
        
        clit_addr_len = sizeof(clit_addr);
        int cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len);
        printf("client ip:%s port:%d\n",
                        inet_ntop(AF_INET,&clit_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),
                        ntohs(clit_addr.sin_port));
        if(cfd == -1){
                sys_err("accept error");
        }
        while(1){
                ret = read(cfd, buf, sizeof(buf));
                write(STDOUT_FILENO, buf, ret);


                for(int i = 0 ; i<ret;i++){
                        buf[i] = toupper(buf[i]);
                }

                write(cfd, buf, ret);
        }

        close(lfd);
        close(cfd);
        /*closesocket(sock);*/
        return 0;
}

socket实现client端

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#define SERV_PORT 9527

void sys_err(const char *str){
        perror(str);
        exit(1);
}

int main(int argc,char *argv[]){

        int cfd;
        int conter = 10;
        char buf[BUFSIZ];

        struct sockaddr_in serv_addr;
        serv_addr.sin_family = AF_INET;
        inet_pton(AF_INET,"127.0.0.1", &serv_addr.sin_addr.s_addr);
        serv_addr.sin_port = htons(SERV_PORT);

        cfd = socket(AF_INET, SOCK_STREAM, 0);
        if(cfd==-1){
                sys_err("socket error");
        }
        int ret = connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
        if(ret != 0){
                sys_err("connect error");
        }

        while(--conter){
                write(cfd,"hello",5);
                ret = read(cfd,buf,sizeof(buf));
                write(STDOUT_FILENO,buf,ret);
        }

        close(cfd);

        return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值