Linux-socket编程以及TCP、UDP实例

socket的基本操作

创建socket

int socket(int domain, int type, int protocol);  
1. domain 指定使用何种的地址类型
    协议  说明
    PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL   UNIX 进程通信协议
    PF_INET/AF_INET Ipv4 网络协议
    PF_INET6/AF_INET6   Ipv6 网络协议
    PF_IPX/AF_IPX IPX-Novell    协议
    PF_NETLINK/AF_NETLINK   核心用户接口装置
    PF_X25/AF_X25   ITU-T X. 25/ISO-8208 协议
    PF_AX25/AF_AX25 业余无线AX. 25 协议
    PF_ATMPVC/AF_ATMPVC 存取原始 ATM PVCs
    PF_APPLETALK/AF_APPLETALK   appletalk (DDP)协议
    PF_PACKET/AF_PACKET 初级封包接口
    PF_INET/AF_INET Ipv4 网络协议
    PF_INET/AF_INET Ipv4 网络协议

2. type的类别。见表:
    类型  说明
    SOCK_STREAM 提供双向连续且可信赖的数据流, 即TCP
    SOCK_DGRAM  使用不连续不可信赖的数据包连接
    SOCK_SEQPACKET  提供连续可信赖的数据包连接
    SOCK_RAW    提供原始网络协议存取
    SOCK_RDM    提供可信赖的数据包连接
    SOCK_PACKET 提供和网络驱动程序直接通信

3. protocol 用来指定socket 所使用的传输协议编号,通常为0
成功返回0 失败返回-1

命名socket

  int bind(int sockfd, struct sockaddr * my_addr, int addrlen);

   0 正确

常用的错误:EACCES,EADDRINUSE

监听socket–创建一个监听队列

int liseten(int socketfd,int backlog)

接受连接

accet(int socketfd,struct sockaddr * my_addr, int addrlen)

从队列中接受一个连接

发起连接

connect(int socketfd,struct sockaddr * my_addr, int addrlen)

关闭连接

close(int fd)

tcp数据读写

recv(int fd,void*buf,size_t len,int flags)
send(int fd,const void *buf,size_t len,int flags)
flag 有一些特别的参数
    持续监听对方的回应
     不经过路由表
     对socket非阻塞
     发送紧急数据
     不接受sig信号等等

udp数据读写

recvfrom(int fd,void*buf,size_t len,int flags,struct sockaddr * my_addr, int addrlen)

sendto(int fd,const void*buf,size_t len,int flags,struct sockaddr * my_addr, int addrlen)

通用数据读写

recvmsg(int fd,struct msghdr*msg,int flags);
sendmsg(int fd,struct msghdr*msg,int flags);
struct msghdr
{
    void* msg_name;
    socklen_t msg_namelen;
    struct iovec*msg_iov;
    int msg_iovlen;
    void* msg_control;
    socklen_t msg_controllen;
    int msg_flags;
};

struct iovec
{
    void *iov_base;
    size_t iov_len;
};

带外标记判断

int sockatmark(int sockfd);

地址信息函数

int getsockname(int socketfd,struct sockaddr * my_addr, int addrlen);//本端的地址信息
int getpeername(int socketfd,struct sockaddr * my_addr, int addrlen);//远端的地址信息

socket选项

获取socket选项
getsockopt(int socketfd,int opt_name,void*option_value,socket_t restrict option_len)
设置socket选项
getsockopt(int socketfd,int opt_name,void*option_value,socket_t restrict option_len)

这个可以查看手册。
选项名称        说明                  数据类型
========================================================================
            SOL_SOCKET
------------------------------------------------------------------------
SO_BROADCAST      允许发送广播数据            int
SO_DEBUG        允许调试                int
SO_DONTROUTE      不查找路由               int
SO_ERROR        获得套接字错误             int
SO_KEEPALIVE      保持连接                int
SO_LINGER        延迟关闭连接              struct linger
SO_OOBINLINE      带外数据放入正常数据流         int
SO_RCVBUF        接收缓冲区大小             int
SO_SNDBUF        发送缓冲区大小             int
SO_RCVLOWAT       接收缓冲区下限             int
SO_SNDLOWAT       发送缓冲区下限             int
SO_RCVTIMEO       接收超时                struct timeval
SO_SNDTIMEO       发送超时                struct timeval
SO_REUSERADDR      允许重用本地地址和端口         int
SO_TYPE         获得套接字类型             int
SO_BSDCOMPAT      与BSD系统兼容              int
========================================================================
            IPPROTO_IP
------------------------------------------------------------------------
IP_HDRINCL       在数据包中包含IP首部          int
IP_OPTINOS       IP首部选项               int
IP_TOS         服务类型
IP_TTL         生存时间                int
========================================================================
            IPPRO_TCP
------------------------------------------------------------------------
TCP_MAXSEG       TCP最大数据段的大小           int
TCP_NODELAY       不使用Nagle算法             int
========================================================================

获取主机信息

根据名字获取主机信息
struct hostent* gethostbyname(const char *name)
根据ip获取主机信息
struct hostent* gethostbyaddr(const void *addr,size_t len,int type)
struct hostent
{
    char *h_name;//主机名
    char** h_aliases;//主机别名,可能有多个
    int h_addrtype;//地址类型
    int h_length;// 地址长度
    char ** h_addr_list//按照网络字节序列列出idp地址列表
}

获取服务信息

//根据 名字,端口号获取服务信息
struct servent*getservbyname(const char *name,const char *proto);
//根据服务类型,端口号获取服务信息
struct servent*getservbyport(int port,const char *proto);
    struct servent{
        char *h_name;//主机名
        char** h_aliases;//主机别名,可能有多个
        int  s_port;//端口号
        char *s_proto;//服务类型,tcp或者upd等

    }

通过主机名获取ip地址

int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );

通过socket地址获取主机名

int getnameinfo (const struct sockaddr *sockaddr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) ;

tcp编程的例子server

//
//  main.cpp
//  linux_socket_api
//
//  Created by bikang on 16/11/2.
//  Copyright (c) 2016年 bikang. All rights reserved.
//

#include <iostream>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

//using namespace std;

#define BUFFER_SIZE 1024


void tsocket(int argc, const char * argv[]);

int main(int argc, const char * argv[]) {
    tsocket(argc,argv);
    return 0;
}
void tsocket(int argc, const char * argv[]){
    if(argc < 3){
        exit(-1);
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);
    int backlog = atoi(argv[3]);

    std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog  << std::endl;

    int fd;
    int check_ret;

    fd = socket(PF_INET,SOCK_STREAM , 0);
    assert(fd >= 0);

    struct sockaddr_in address;
    bzero(&address,sizeof(address));

    //转换成网络地址
    address.sin_port = htons(port);
    address.sin_family = AF_INET;
    //地址转换
    inet_pton(AF_INET, ip, &address.sin_addr);
    //设置socket buffer大小
    int recvbuf = 4096;
    int len = sizeof( recvbuf );
    setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) );
    getsockopt( fd, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len );
    printf( "the receive buffer size after settting is %d\n", recvbuf );



    //绑定ip和端口
    check_ret = bind(fd,(struct sockaddr*)&address,sizeof(address));
    assert(check_ret >= 0);

    //创建监听队列,用来存放待处理的客户连接
    check_ret = listen(fd, backlog);
    assert(check_ret >= 0);

    struct sockaddr_in addressClient;
    socklen_t clientLen = sizeof(addressClient);
    //接受连接,阻塞函数
    int connfd = accept(fd, (struct sockaddr*)&addressClient, &clientLen);
    if(connfd < 0){
        std::cout << "accept error";
    }else{
        //打印客户端信息
        char showData[INET_ADDRSTRLEN];
        std::cout <<inet_ntop(AF_INET,&addressClient.sin_addr,showData,INET_ADDRSTRLEN)<<":" <<ntohs(addressClient.sin_port)<<std::endl;

        //接受数据
        const int BUF_LEN = 1024;
        char sockBuf[BUF_LEN];
        size_t ret;

        memset(sockBuf, '\0', BUF_LEN);
        ret = recv(connfd, sockBuf, BUF_LEN-1, 0);
        printf("ret=%ld,msg=%s\n",ret,sockBuf);

        memset(sockBuf, '\0', BUF_LEN);
        ret = recv(connfd, sockBuf, BUF_LEN-1, MSG_OOB);
        printf("ret=%ld,msg=%s\n",ret,sockBuf);

        memset(sockBuf, '\0', BUF_LEN);
        ret = recv(connfd, sockBuf, BUF_LEN-1, 0);
        printf("ret=%ld,msg=%s\n",ret,sockBuf);

        //获取本地socket信息
        struct sockaddr_in tmpAddress;
        clientLen = sizeof(tmpAddress);
        getsockname(fd, (struct sockaddr*)&tmpAddress, &clientLen);
        std::cout <<inet_ntop(AF_INET,&tmpAddress.sin_addr,showData,INET_ADDRSTRLEN)<<":" <<ntohs(tmpAddress.sin_port)<<std::endl;
        //获取远端socket信息
        getpeername(connfd,(struct sockaddr*)&tmpAddress, &clientLen );
        std::cout <<inet_ntop(AF_INET,&tmpAddress.sin_addr,showData,INET_ADDRSTRLEN)<<":" <<ntohs(tmpAddress.sin_port)<<std::endl;



        close(connfd);
    }

    close(fd);
}

tcp编程的例子client

//
//  main.cpp
//  linux_socket_api_client
//
//  Created by bikang on 16/11/2.
//  Copyright (c) 2016年 bikang. All rights reserved.
//
#include <iostream>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>


void tserver(int argc, const char * argv[]);

int main(int argc, const char * argv[]) {
    tserver(argc,argv);
    return 0;
}
void tserver(int argc, const char * argv[]){
    std::cout << "t server" << std::endl;
    if(argc < 3){
        exit(-1);
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);
    int backlog = atoi(argv[3]);

    std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog  << std::endl;

    int fd;
    int check_ret;

    fd = socket(PF_INET,SOCK_STREAM , 0);
    assert(fd >= 0);

    int sendbuf = 4096;
    int len = sizeof( sendbuf );
    setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) );
    getsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len );
    printf( "the send buffer size after settting is %d\n", sendbuf );

    struct sockaddr_in address;
    bzero(&address,sizeof(address));

    //转换成网络地址
    address.sin_port = htons(port);
    address.sin_family = AF_INET;
    //地址转换
    inet_pton(AF_INET, ip, &address.sin_addr);
    check_ret = connect(fd, (struct sockaddr*) &address, sizeof(address));
    assert(check_ret >= 0);
    //发送数据
    const char* oob_data = "abc";
    const char* normal_data = "my boy!";

    send(fd, normal_data, strlen(normal_data), 0);
    send(fd, oob_data, strlen(oob_data), MSG_OOB);
    send(fd, normal_data, strlen(normal_data), 0);


    close(fd);
}
udp编程的例子server

#include <iostream>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

//using namespace std;

#define BUFFER_SIZE 1024


void tsocket(int argc, const char * argv[]);

int main(int argc, const char * argv[]) {
    tsocket(argc,argv);
    return 0;
}
void tsocket(int argc, const char * argv[]){
    if(argc < 3){
        exit(-1);
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);
    int backlog = atoi(argv[3]);

    std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog  << std::endl;

    int fd;
    int check_ret;

    fd = socket(PF_INET,SOCK_DGRAM , 0);
    assert(fd >= 0);

    struct sockaddr_in address;
    bzero(&address,sizeof(address));

    //转换成网络地址
    address.sin_port = htons(port);
    address.sin_family = AF_INET;
    //地址转换
    inet_pton(AF_INET, ip, &address.sin_addr);

    //绑定ip和端口
    check_ret = bind(fd,(struct sockaddr*)&address,sizeof(address));
    assert(check_ret >= 0);



    while(1){

        char buffer[BUFFER_SIZE];
        struct sockaddr_in addressClient;
        socklen_t clientLen = sizeof(addressClient);
        memset(buffer, '\0', BUFFER_SIZE);
        //获取信息
        if(recvfrom(fd, buffer, BUFFER_SIZE-1,0,(struct sockaddr*)&addressClient, &clientLen) == -1) 
        { 
           perror("Receive Data Failed:"); 
           exit(1); 
        } 
        printf("buffer=%s\n", buffer);
    }
    close(fd);
}

udp编程的例子client

//
//  main.cpp
//  linux_socket_api_client
//
//  Created by bikang on 16/11/2.
//  Copyright (c) 2016年 bikang. All rights reserved.
//
#include <iostream>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>


void tserver(int argc, const char * argv[]);

int main(int argc, const char * argv[]) {
    tserver(argc,argv);
    return 0;
}
void tserver(int argc, const char * argv[]){
    std::cout << "t server" << std::endl;
    if(argc < 3){
        exit(-1);
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);
    int backlog = atoi(argv[3]);

    std::cout << "ip=" << ip << " port="<<port << " backlog=" << backlog  << std::endl;

    int fd;
    int check_ret;

    fd = socket(PF_INET,SOCK_DGRAM , 0);
    assert(fd >= 0);

    struct sockaddr_in address;
    bzero(&address,sizeof(address));

    //转换成网络地址
    address.sin_port = htons(port);
    address.sin_family = AF_INET;
    //地址转换
    inet_pton(AF_INET, ip, &address.sin_addr);
    //发送数据
    const char* normal_data = "my boy!";
    if(sendto(fd, normal_data, strlen(normal_data),0,(struct sockaddr*)&address,sizeof(address)) < 0) 
    { 
      perror("Send File Name Failed:"); 
      exit(1); 
    }
    close(fd);
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值