简单socket的尝试

简单socket的尝试

参考博客 linux下socket编程归纳记录 这篇博客是我学长的学长写的,进过两天简单的学习后,我决定写一篇博客归纳一下暂时学到的知识。

双向通信

       原博客简单地将socket的功能基本实现一遍,但是是单向通信的。我在看了个半懂不懂的情况下,觉得可以尝试着在源程序的基础上进行改造,在一些周折之后,如愿实现了一个可以双向通信的程序。

客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main(void)
{

        int st = socket(AF_INET, SOCK_STREAM, 0);       //初始化socket,

        struct sockaddr_in addr;                //定义一个IP地址的结构
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;              //设置结构地址类型为TCP/IP地址
        addr.sin_port = htons(8080);                //指定一个端口号:8080,htons:将short类型从host字节类型到net字节类型转化
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");      //将字符串类型的IP地址转化为int,赋给addr结构成员.

        // 调用connect连接到结构addr(即服务器)指定的IP地址和端口号          
        if (connect(st, (struct sockaddr *) &addr, sizeof(addr)) == -1)
        {
            printf("connect failed %s\n", strerror(errno));
            return EXIT_FAILURE;
        }

        char s[1024];               // 通信时传输的文本
        memset(s, 0, sizeof(1024));     
        while (strcmp(s, "exit"))   // 当自身输入exit后将终止通信,随后关闭用于连接服务器的套接字
        {
            printf("myself: ");     // 输入提示
            scanf("%s", s);         // 输入文本
            printf("\n");
            s[strlen(s)] = '\0';    // 在文本末尾加入终止符
            if (send(st, s, strlen(s)+1, 0) == -1)//发送buf的数据
            {
                printf("send failed %s\n", strerror(errno));
                return EXIT_FAILURE;
            }
            if (!strcmp(s, "exit"))  // 如果服务器发来exit的文本内容,则终止通信
            {
                break;
            }
            recv(st, s, sizeof(s), 0);
            printf("server: %s\n\n", s);
        }
        close(st);                  //关闭socket
        return EXIT_SUCCESS;
}

服务器端
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>


int main(int arg, char *args[])
{
    int st = socket(AF_INET, SOCK_STREAM, 0);//初始化一个socket

    int on = 1;
    if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
    {
            printf("setsockopt failed %s\n", strerror(errno));
            return EXIT_FAILURE;
    }


    struct sockaddr_in addr;     //定义一个IP地址结构
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;   //将addr结构的属性定位为TCP/IP地址
    addr.sin_port = htons(8080); //将本地字节顺序转化为网络字节顺序,网络字节序是大端字节序,x86是小端字节序
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");     //INADDR_ANY代表这个server上所有的地址

    //将IP与server程序绑定
    if (bind(st, (struct sockaddr *) &addr, sizeof(addr)) == -1)
    {
            printf("bind failed %s\n", strerror(errno));
            return EXIT_FAILURE;
    }

    //server端开始listen,
    if (listen(st, 20) == -1)
    {
            printf("listen failed %s\n", strerror(errno));
            return EXIT_FAILURE;
    }
    char s[1024];
    int client_st = 0;//client端socket
    //socklen_t len = 0;
    struct sockaddr_in client_addr;//表示client端的IP地址
    //void *p = &client_addr;
    int i;

    memset(&client_addr, 0, sizeof(client_addr));
    socklen_t len = sizeof(client_addr);
    client_st = accept(st, (struct sockaddr *)&client_addr, &len);

    while (1)
    {
        if (client_st == -1)
        {
            printf("accept failed %s\n", strerror(errno));
            return EXIT_FAILURE;
        }
        memset(s, 0, sizeof(1024));
        int rc = recv(client_st, s, sizeof(s), 0);
        printf("client: %s\n\n", s);
        if (!strcmp(s, "exit"))
        {
            break;
        }
        printf("myslef: ");
        scanf("%s", s);
        printf("\n");
        // 这里需要注意一点,不能将服务器本身的嵌套字作为媒介,为是要将接收客户端的嵌套字发送回去,否则会造成程序终止   
        send(client_st, s, strlen(s)+1, 0);  
    }
    close(client_st);
    close(st);//关闭server端listen的socket
    return EXIT_SUCCESS;
}

改造好后的程序的局限

这个程序虽然能进行双向通信,但是还是具有很多局限性,比如说,当服务器端(客户端)在向对方发送给了一条文本消息后,必须等待对方的回应的文本消息,才能继续输入条文本消息发送给对方,如果对方不发送消息回应的话,服务器端(客户端)就不能继续输入文本并发送。
我个人的理解是需要用到多线程编程,比如将接收消息和发送消息放到两个不同的线程中,这样的话就可以将两者相对独立开来。我前段日子有简单地接触过多线程编程,但是是在windows平台下编程的,下等我进一步理解完socket的工作原理后,我准备结合多线程完善一下这个小聊天程序。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值