一个socket的基础例子

我不得不说socket编程对于我来说是很复杂的,以前总是说socket,但到现在来说还是没有把他弄懂,即使当时记得了但过了几天又忘记了,所以需要常常看才能牢记。

socket编程的基础函数有socket(),bind(), listen(),accept(),send(),sendto(),recv(),recvfrom()根据客户端还是服务端不一样,针对udp,tcp又是不一样的,先对这几个函数进行说明

socket()------该函数用于建立一个socket连接,可以指定socket类型等信息,在建立socket连接之后,可以对sockaddr或sockaddr_in结构体进行初始化,来保存所建立的socket 

                       地址信息

bind()---------用于将本地ip绑定到端口号,绑定其他ip不能成功,主要用于TCP中,在upd中则没有必要

listen()--------在创建套接字和绑定地址之后需要在该套接字上接受新的请求,listen()可以用来创建一个等待队列,用于存放未处理的客户端请求

accept()-------服务端调用listen之后,调用此函数等待并接收客户端的请求,通常他从listen()函数创建的等待队列中取出第一个未处理的连接请求

connetc()------在TCP中用于bind()之后的客户端用于与服务器建立连接,而在UDP中由于没有bind()函数,这个connect函数有点类似于bind()函数的作用

recv(),recv()---用于数据的发送和接收,在udp中可以在connet()建立连接之后再使用

sendto(),recvfrom()---在TCP中作用等同于send(),recv(),而在UDP中可以用在之前没有使用connect()的情况,这两个函数可以自动寻找指定地址并进行连接

服务器和客户端使用TCP协议的流程如下:                                                   

一个socket的基础例子_第1张图片

对于客户端有时不需要进行bind()调用,http://blog.csdn.net/smilestone322/article/details/8449165

服务器和客户端使用UDP协议的流程如下:

一个socket的基础例子_第2张图片


下面是各个函数的使用语法:

socket()使用语法:

一个socket的基础例子_第3张图片

一个socket的基础例子_第4张图片

bind()函数的使用语法:

一个socket的基础例子_第5张图片

端口号和地址在my_addr中给出,如果不指定地址则内核随意分配一个临时端口给程序

listen()函数语法如下:

一个socket的基础例子_第6张图片

accept()函数语法如下:

一个socket的基础例子_第7张图片

一个socket的基础例子_第8张图片

connect()函数语法如下:

一个socket的基础例子_第9张图片

send()函数语法:

一个socket的基础例子_第10张图片

recv函数语法:

一个socket的基础例子_第11张图片

sendto语法:

一个socket的基础例子_第12张图片

recvfrom函数语法:

一个socket的基础例子_第13张图片

下面是一个c/s的例子

server.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 4321
#define BUFFER_SIZE 1024
#define MAX_QUE_CONN_NM 5
int main()
{
    struct sockaddr_in server_sockaddr,client_sockaddr ;
    int sin_size, recvbytes ;
    int sockfd,client_fd ;
    char buf[BUFFER_SIZE] ;
    /*建立socket连接*/
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket") ;
        exit(1) ;
    }
    printf("socket id = %d\n", sockfd) ;
    /*sockaddr_in结构体相关参数*/
		server_sockaddr.sin_family = AF_INET ;
    server_sockaddr.sin_port = htons(PORT) ;
    server_sockaddr.sin_addr.s_addr = INADDR_ANY ;
    bzero(&(server_sockaddr.sin_zero), 8) ;

    int i = 1 ;//允许重复使用本地地址与套接字进行绑定
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) ;
		//绑定ip与端口号
    if (bind(sockfd, (struct sockaddr *)&server_sockaddr,
                    sizeof (struct sockaddr)) == -1)
    {
        perror("bind error") ;
        exit(1) ;
    }
    printf("bind success\n") ;
    /*调用listen()函数,创建未处理请求队列*/
    if (listen(sockfd, MAX_QUE_CONN_NM) == -1)
    {
        perror("listen error\n") ;
        exit (1) ;
    }
    printf("listen....\n") ;
		//等待客户连接,此处返回客户端的socket描述符
    if((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr,
               &sin_size)) == -1)
    {
        perror("accept") ;
        exit(1) ;
    }

    memset(buf, 0, sizeof(buf)) ;
    /*调用recv()函数接收客户端请求*/
    if ((recvbytes = recv(client_fd, buf, BUFFER_SIZE, 0)) == -1)
    {
        perror("recv") ;
        exit(1) ;
    }
    printf("recevie a message :%s\n", buf) ;
    close(sockfd) ;
    exit(0) ;
}

对应client端的实例如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 4321
#define BUFFER_SIZE 1024
int main(int argc, char *argv[])
{
    int sockfd, sendbytes ;
    char buf[BUFFER_SIZE] ;
    struct hostent *host ;
    struct sockaddr_in serv_addr ;
    if (argc < 3)
    {
        fprintf(stderr, "USAGE: ./client Hostname(or ip address) Text\n") ;
        exit(1) ;
    }
		//由主机名获得ip
    if ((host = gethostbyname(argv[1])) == NULL)
    {
        perror("gethostbyname") ;
        exit(1) ;
    }

    memset(buf, 0, sizeof(buf)) ;
    sprintf(buf, "%s", argv[2]) ;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) ==-1)
    {
        perror("socket") ;
        exit(1) ;
    }

    serv_addr.sin_family = AF_INET ;
    serv_addr.sin_port = htons(PORT) ;
    serv_addr.sin_addr = *((struct in_addr*)host->h_addr) ;
    bzero(&(serv_addr.sin_zero), 8) ;

    if (connect(sockfd, (struct sockaddr*)&serv_addr,
                        sizeof(struct sockaddr)) == -1)
    {
        perror("connetc") ;
        exit(1) ;
    }
    if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)
    {
        perror("send") ;
        exit (1) ;
    }
    close(sockfd) ;
    exit(0) ;
}

执行客户端:

服务端将会接收消息:



 



你可能感兴趣的:(linux)