zoukankan      html  css  js  c++  java
  • Linux下C语音实现socket发送和接收的小程序

    1、什么是socket套接字

    socket其实就是计算机通信的端口,可以实现两个计算机之间的通信的一个接口,应用程序在网络上传输就是通过这个借口实现。

    socket分为三种类型:

    字节流套接字(Stream Socket),最常用socket类型,TCP协议使用此类接口。提供面向连接(建立虚拟电路)、无差错、发送顺序一致、无记录边界和非重复的网络信包传输

    数据报套接字(Datagram Socket),UDP协议使用此类接口,提供无连接服务,它以独立的信包进行网络传输,信包最大长度为32KB,传输不保证顺序性、可靠性和无重复性,它通常用于单个报文传输或可靠性不重复的场合。数据报套接字接口的一个重要特点是它保留了记录边界。

    原始数据报套接字(Raw Socket),提供对网络下层通讯协议(eg:IP协议)的直接访问,一般不是提供给普通用户的,主要用于开发新的协议或者用于提取协议教隐蔽的功能

    2、 客户服务器通信流程

     

    • 创建套接字

      #include <sys/types.h> /* See NOTES */

      #include <sys/socket.h>

      int socket(int domain, int type, int protocol);//返回sockfd

      函数定义:这个函数返回套接字描述符,它唯一标识一个socket,后续操作用它作为参数来进行一些读写操作,socket函数的三个参数分别为:

    1. 协议域:AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等
    2. socket类型:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等
    3. protocal传输协议类型:IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等

      返回值:整个则返回一个新的描述符,错误返回-1,并有对应的errorno详情见 https://linux.die.net/man/2/socket

    • 绑定IP和port

      #include <sys/types.h>

      #include <sys/socket.h>

      int bind(int sockfd, const struct sockaddr *addr,

             socklen_t addrlen);

    1. sockfd:返回新套接字的描述符
    2. addr:赋给套接字的地址
    3. addrlen:地址的长度

      返回值:正确返回0,错误返回-1,详情见 https://linux.die.net/man/2/bind

    • 监听连接

      #include <sys/types.h>

      #include <sys/socket.h>

      int listen(int sockfd, int backlog);

    1. sockfd:返回新套接字并已绑定地址的描述符
    2. backlog:限制请求连接队列的最大长度,当请求队列满了再次来连接请求就会报ECONNREFUSED,除非底层协议支持重传,这样就会等待前面请求数据传送完毕再进行请求

      返回值:正确返回0,错误返回-1,详情见 https://linux.die.net/man/2/listen

    • 接收连接

      #include <sys/types.h>

      #include <sys/socket.h>

      int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    1. sockfd:返回新套接字并已绑定地址处于监听状态的描述符
    2. addr:准备接受请求数据的地址,一般为客户端套接字地址
    3. addrlen:客户端套接字地址长度

      返回值:成功则返回一个非负的SOCKET类型的值,表示接收到的套接字描述符,错误返回-1,并有对应的errorno,详情见https://linux.die.net/man/2/accept

    3、C 程序

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <stdint.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <error.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/time.h>
    int main(){
        struct sockaddr_in server_addr, client_addr;
        int socketserver;
        int err;
        int socketclient;as
        struct timeval timeout;
        char rcvbuf[100];
        char sedbuf[100000];
        timeout.tv_sec=5;
        timeout.tv_usec=0;
        //socket buff size
        int opt=100000;
    
        if((socketserver = socket(AF_INET,SOCK_STREAM,0)) == -1)
            return 1;
        //接受时限5s
        //setsockopt(socketserver, SOL_SOCKET,SO_RCVTIMEO, (char*)&timeout,sizeof(timeout));
        //发送时限5s
        //setsockopt(socketserver, SOL_SOCKET,SO_SNDTIMEO, (char*)&timeout,sizeof(timeout));
        //接收缓冲区
        setsockopt(socketserver, SOL_SOCKET, SO_RCVBUF, (const char*)&opt,sizeof(opt));
        //发送缓冲区
        setsockopt(socketserver, SOL_SOCKET, SO_SNDBUF, (const char*)&opt,sizeof(opt));
        //设置服务器地址信息设置
        server_addr.sin_family = AF_INET;                    //TCP
        server_addr.sin_port = htons(8080);                  //网络字节顺序采用大端模式
        server_addr.sin_addr.s_addr = INADDR_ANY;            //本地IP地址
        // server_addr.sin_addr.s_addr=htonl(127.0.0.1);
        printf("server port:%ld
    ", ntohs(server_addr.sin_port));
        memset(server_addr.sin_zero,'',sizeof(server_addr.sin_zero));
        err=bind(socketserver, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
        if(err == -1){
            perror("bind error:");
            return 1;
         }
        if((err = listen(socketserver,10)) == -1){
            perror("listen error:");
            return 1;
         }
        while(1){
            int len = sizeof(struct sockaddr);
            head:
            if((socketclient = accept(socketserver,(struct sockaddr *)&client_addr,&len)) == -1){
               if(errno == 11){
                puts("timeout");
                  goto head;
                 }
                else{
                perror("accpet error:");
                return 1;
                }
            }
          write(socketclient,sedbuf,100000);
          printf("send sucess
    ");
          // handle the connection of client
          while(1){
             memset(rcvbuf,'',100);
             len = read(socketclient,rcvbuf,40);
             if(len <=0){
                   if(errno == EINTR || errno == EAGAIN)// except interruption XXX 92                
                continue; 
                 else{
                     perror("client down:");
                     break;
                  }
             }
               printf(" I received  %s
    ",rcvbuf);
          }//while(1) handle the connection of client
      }//while(1) 
    return 0;
    }
    View Code
  • 相关阅读:
    如何获取SQL Server数据库连接字符串的某些部分
    .NET同步原语Barrier简介
    模版引擎RazorEngine简介
    如何使用SQL Server实现SignalR的横向扩展
    SignalR的客户端.NET Client介绍
    一个简单的SignalR例子
    看视频学SignalR—在微软虚拟学院学习SignalR
    看视频学Bootstrap—在微软虚拟学院学习Bootstrap
    C# 窗口与控件的相关操作
    opencv——常见的操作
  • 原文地址:https://www.cnblogs.com/guoxueyuan/p/6474254.html
Copyright © 2011-2022 走看看