基于TCP的客户端、服务器端socket编程

服务器端流程

1.创建socket 

 socket是一个结构体,被创建在内核中

sockfd=socket(AF_INET,SOCK_STREAM,0); //AF_INT:ipv4, SOCK_STREAM:tcp协议

2.调用bind函数

  将socket和地址(包括ip、port)绑定。

  需要定义一个结构体地址,以便于将port的主机字节序转化成网络字节序

      struct sockaddr_in serveraddr; //地址结构体

  bind函数

       bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))

3.listen监听,将接收到的客户端连接放入队列

listen(sockfd,10) //第二个参数是队列长度

4.调用accept函数,从队列获取请求,返回socket描述符

  如果无请求,将会阻塞,直到获得链接

int fd=accept(sockfd, (struct sockaddr*)&clientaddr, &clientaddr_len);

5.调用IO函数和客户端双向通信

6.关闭accept返回的socket

close(fd);

服务器代码:

#include "iostream"
#include "netdb.h"
#include "stdio.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "unistd.h"
#include "arpa/inet.h"
#include "string.h"
#include "memory.h"
#include "signal.h"
#include "time.h"

int sockfd;

void sig_handler(int signo)
{
    if(signo==SIGINT)
    {
        printf("Server close \n");
        close(sockfd);
        exit(1);
    }
}

//输出连接上来的客户端相关信息
void out_addr(struct sockaddr_in *clientaddr)
{
    //将端口从网络字节序转成主机字节序
    int port =ntohs(clientaddr->sin_port);
    char ip[16];
    memset (ip,0,sizeof(ip));
    inet_ntop(AF_INET,
            &clientaddr->sin_addr.s_addr,ip,sizeof(ip));
    printf("client:%s(%d)connected\n",ip,port);
}

void do_service(int fd)
{
    //获取系统时间
    long t=time(0);
    char *s=ctime(&t);
    size_t size=strlen(s)*sizeof(char);
    //将服务器端的系统时间写到客户端
    if(write(fd,s,size)!=size)
    {
        perror("write error");
    }
}

int main(int argc,char *argv[])
{
    if(argc<2)
    {
        printf("usage:%s #port\n",argv[0]);
        exit(1);
    }

    if(signal(SIGINT,sig_handler)==SIG_ERR)
    {
        perror("signal sigint error");
        exit(1);
    }

    /*1. 创建socket
     AF_INT:ipv4
     SOCK_STREAM:tcp协议
    */
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0){
        perror("socket error");
        exit(1);
    }

    /*2:调用bind函数绑定socket和地址*/

    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    //往地址中填入ip,port,internet类型
    serveraddr.sin_family=AF_INET;  //ipv4
    serveraddr.sin_port=htons(atoi(argv[1]));  //htons主机字节序转成网络字节序

    serveraddr.sin_addr.s_addr=INADDR_ANY;

    if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))<0)
    {
        perror("bind error");
        exit(1);

    }

    /*3:调用listen函数监听(指定port监听)
    通知操作系统区接受来自客户顿的连接请求
    第二个参数:指定队列长度
    */

    if(listen(sockfd,10)<0)
    {
        perror("listen error");

    }

    /*4:调用accept函数从队列中获得一个客户端的请求连接
    */

    struct sockaddr_in clientaddr;
    socklen_t clientaddr_len=sizeof(clientaddr);

    while(1){
        int fd=accept(sockfd,
                (struct sockaddr*)&clientaddr,
                  &clientaddr_len);
        if(fd<0){
            perror("accept error");
            continue;
        }

        /*5:调用IO函数(read/write)和
            连接的客户端进行双向通信
        */
        out_addr(&clientaddr);
        do_service(fd);

        /*6.关闭socket*/
        close(fd);
    }

    return 0;
}

客户端代码:

#include "netdb.h"
#include "sys/socket.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "memory.h"
#include "unistd.h"
#include <arpa/inet.h>

int main(int argc,char *argv[])
{
    if(argc<3)
    {
        printf("usage:%s ip port \n",argv[0]);
        exit(1);
    }

    /*步骤1:创建socket*/
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0)
    {
        perror("socket error");
        exit(1);
    }

    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_port=htons(atoi(argv[2]));

    //主机字节序转换成网络字节序
    inet_pton(AF_INET,argv[1],
            &serveraddr.sin_addr.s_addr);

    /*步骤2:客户端调用connect函数连接到服务器

    */
    if(connect(sockfd,(struct sockaddr*)&serveraddr,
                sizeof(serveraddr))<0)
    {
        perror("connect error");
        exit(1);
    }

    /*步骤3:调用IO函数(read/write)和服务器端双向通信*/
    char buffer[1024];
    memset(buffer,0,sizeof(buffer));
    size_t size;

    if((size=read(sockfd,
                    buffer,sizeof(buffer)))<0)
    {
        perror("read error");
    }

    if(write(STDOUT_FILENO,buffer,size)!=size)
    {
        perror("write error");
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值