zoukankan      html  css  js  c++  java
  • linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢!

    这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到client的连接后,发送数据给client;client在接受到数据后打印出来,然后关闭。程序里有具体的说明,当中对具体的结构体和函数的实现能够參考其它资料。

    程序说明: 这里server的port号和ip地址使用固定的设置,移植时能够依据详细情况更改,能够改写为參数传递更好,这里为了方便,使用固定的。

    移植时服务端能够不用更改,编译后可直接执行;client将ip改为server的地址,然后编译执行。能够使用netstat 进行查看对应的执行状态。


    /*************************************
    文件名称: server.c 
    linux 下socket网络编程简例  - 服务端程序
    serverport设为 0x8888   (port和地址可依据实际情况更改,或者使用參数传入)
    server地址设为 192.168.1.104
    作者:kikilizhm#163.com (将#换为@)
    */
    
    #include <stdlib.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <linux/in.h>
    #include <string.h>
    
    int main()
    {
    int sfp,nfp; /* 定义两个描写叙述符 */
    struct sockaddr_in s_add,c_add;
    int sin_size;
    unsigned short portnum=0x8888; /* 服务端使用端口 */
    
    printf("Hello,welcome to my server !
    ");
    sfp = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == sfp)
    {
        printf("socket fail ! 
    ");
        return -1;
    }
    printf("socket ok !
    ");
    
    /* 填充serverport地址信息,以便以下使用此地址和port监听 */
    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即全部 */
    s_add.sin_port=htons(portnum);
    /* 使用bind进行绑定port */
    if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("bind fail !
    ");
        return -1;
    }
    printf("bind ok !
    ");
    /* 開始监听对应的port */
    if(-1 == listen(sfp,5))
    {
        printf("listen fail !
    ");
        return -1;
    }
    printf("listen ok
    ");
    
    while(1)
    {
    sin_size = sizeof(struct sockaddr_in);
    /* accept服务端使用函数,调用时即进入堵塞状态,等待用户进行连接,在没有client进行连接时,程序停止在此处,
       不会看到后面的打印,当有client进行连接时,程序立即运行一次,然后再次循环到此处继续等待。
       此处accept的第二个參数用于获取client的port和地址信息。
        */
    nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
    if(-1 == nfp)
    {
        printf("accept fail !
    ");
        return -1;
    }
    printf("accept ok!
    Server start get connect from %#x : %#x
    ",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));
    
    /* 这里使用write向client发送信息,也能够尝试使用其它函数实现 */
    if(-1 == write(nfp,"hello,welcome to my server 
    ",32))
    {
        printf("write fail!
    ");
        return -1;
    }
    printf("write ok!
    ");
    close(nfp);
    
    }
    close(sfp);
    return 0;
    }
    



    /*************************************
    文件名称: client.c 
    linux 下socket网络编程简例  - client程序
    serverport设为 0x8888   (port和地址可依据实际情况更改,或者使用參数传入)
    server地址设为 192.168.1.104
    作者:kikilizhm#163.com (将#换为@)
    */
    
    #include <stdlib.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <linux/in.h>
    #include <string.h>
    
    int main()
    {
    int cfd; /* 文件描写叙述符 */
    int recbytes;
    int sin_size;
    char buffer[1024]={0};    /* 接受缓冲区 */
    struct sockaddr_in s_add,c_add; /* 存储服务端和本端的ip、port等信息结构体 */
    unsigned short portnum=0x8888;  /* 服务端使用的通信端口,能够更改,需和服务端同样 */
    
    printf("Hello,welcome to client !
    ");
    /* 建立socket 使用因特网,TCP流传输 */
    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == cfd)
    {
        printf("socket fail ! 
    ");
        return -1;
    }
    printf("socket ok !
    ");
    /* 构造server端的ip和port信息,详细结构体能够查资料 */
    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr= inet_addr("192.168.1.104"); /* ip转换为4字节整形,使用时须要依据服务端ip进行更改 */
    s_add.sin_port=htons(portnum); /* 这里htons是将short型数据字节序由主机型转换为网络型,事实上就是
        将2字节数据的前后两个字节倒换,和相应的ntohs效果、实质同样,仅仅只是名字不同。htonl和ntohl是
        操作的4字节整形。将0x12345678变为0x78563412,名字不同,内容两两同样,普通情况下网络为大端,
        PPC的cpu为大端,x86的cpu为小端,arm的能够配置大小端,须要保证接收时字节序正确。
     */
    
    printf("s_addr = %#x ,port : %#x
    ",s_add.sin_addr.s_addr,s_add.sin_port); /* 这里打印出的是小端
        和我们平时看到的是相反的。 */
    
    /* client连接server,參数依次为socket文件描写叙述符,地址信息,地址结构大小 */
    if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("connect fail !
    ");
        return -1;
    }
    printf("connect ok !
    ");
    /*连接成功,从服务端接收字符*/
    if(-1 == (recbytes = read(cfd,buffer,1024)))
    {
        printf("read data fail !
    ");
        return -1;
    }
    printf("read ok
    REC:
    ");
    
    buffer[recbytes]='';
    printf("%s
    ",buffer);
    
    getchar(); /* 此句为使程序暂停在此处,能够使用netstat查看当前的连接 */
    close(cfd); /* 关闭连接,本次通信完毕 */
    return 0;
    
    
    
    }
    


    执行截图:



  • 相关阅读:
    线段树练习两题
    DP+单调队列 codevs 1748 瑰丽华尔兹(还不是很懂具体的代码实现)
    线段树和树状数组问题补充
    一些常见的优化:读入优化,滚动数组
    单调队列应用--BZOJ 3831 Little Bird
    单调队列练习之广告印刷
    详解--单调队列 经典滑动窗口问题
    数据结构--栈 codevs 1107 等价表达式
    离散化+线段树 POJ 3277 City Horizon
    求次短路 codevs 1269 匈牙利游戏
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4310332.html
Copyright © 2011-2022 走看看