Linux下socket通信

(一)socket通信简介

       网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“端口”可以唯一标识主机中的应用程序(进程)。这样利用二元组(ip地址,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。 TCP/IP协议族包括运输层、网络层、链路层,而socket所在位置如图,Socket是应用层与TCP/IP协议族通信的中间软件抽象层。
在这里插入图片描述
       Socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”。在许多操作系统中,套接字API最初是作为UNIX操作
系统的一部分而开发的,所以套接字API与系统的其他I/O设备集成在一起。应用程序要为因特网通信而创建一个套接字(socket)时,操作系统就返回一个小整数作为描述符(descriptor)来标识这个套接字。然后应用程序以该描述符作为传递参数,通过调用相应函数(如read、write、close等)来完成某种操作(如从套接字中读取或写入数据)。在生活中,A要电话给B,A拨号,B听到电话铃声后提起电话,这时A和B就建立起了连接,A和B就可以讲话了。等交流结束,挂断电话结束此次交谈。 打电话很简单解释了这工作原理:“open—write/read—close”模式。下面是网络socket通信的基本流程:
在这里插入图片描述

(二)socket服务器代码

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

#define LISTEN_PORT          8889
#define BACKLOG              13

int main(int argc, char **argv)
{
    int                     rv = -1;
    int                     listen_fd,  client_fd = -1;
    struct sockaddr_in      serv_addr;             
    struct sockaddr_in      cli_addr;
    socklen_t               cliaddr_len;
    char                    buf[1024]; 
    
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_fd < 0 )
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -1;
    }
    printf("socket create fd[%d]\n", listen_fd);

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;        
    serv_addr.sin_port = htons(LISTEN_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if( bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 )
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -2;
    }
    printf("socket[%d] bind on port[%d] for all IP address ok\n", listen_fd, LISTEN_PORT);

    listen(listen_fd, BACKLOG); 
    
    while(1)   
    {
        printf("\nStart waiting and accept new client connect...\n", listen_fd);
        client_fd = accept(listen_fd, (struct sockaddr*)&cli_addr, &cliaddr_len);
        if(client_fd < 0)
        {
            printf("accept new socket failure: %s\n", strerror(errno));
            return -2;
        }
        printf("Accept new client[%s:%d] with fd [%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), client_fd);


        memset(buf, 0, sizeof(buf));        
        if( (rv=read(client_fd, buf, sizeof(buf))) < 0)
	{
		printf("Read data from client socket[%d] failure: %s\n", client_fd, strerror(errno));
		close(client_fd);
		continue;
	}
	else if( rv == 0 )
	{
		printf("client socket[%d] disconnected\n", client_fd);
		close(client_fd);
		continue;
	}
	printf("read %d bytes data from client[%d] and echo it back: '%s'\n", rv, client_fd, buf);

	if( write(client_fd, buf, rv) < 0 )
	{
	       	printf("Write %d bytes data back to client[%d] failure: %s\n", rv, client_fd, strerror(errno));
		close(client_fd);
	}
	
        sleep(1);
        close(client_fd); 
    } 
    close(listen_fd);
}

(二)socket客户端代码

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

#define SERVER_IP          "127.0.0.1"
#define SERVER_PORT        8889
#define MSG_STR            "Hello, Unix Network Program World!"

int main(int argc, char **argv)
{
    int                     conn_fd = -1;
    int                     rv = -1;    
    char                    buf[1024]; 
    struct sockaddr_in      serv_addr;

    conn_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(conn_fd < 0)
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -1;
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVER_PORT);
    inet_aton( SERVER_IP, &serv_addr.sin_addr );

    if( connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))  < 0)
    {
        printf("connect to server [%s:%d] failure: %s\n", SERVER_IP, SERVER_PORT, strerror(errno));
        return 0;
    }
    
    if( write(conn_fd, MSG_STR, strlen(MSG_STR)) < 0 )
    {
        printf("Write data to server [%s:%d] failure: %s\n", SERVER_IP, SERVER_PORT, strerror(errno));
	goto cleanup;
    }
    
    memset(buf, 0, sizeof(buf));
    rv = read(conn_fd, buf, sizeof(buf));    
    if(rv < 0)
    {
	    printf("Read data from server failure: %s\n", strerror(errno));
	    goto cleanup;
    }
    else if( 0 == rv )
    {
	    printf("Client connect to server get disconnected\n");
	    goto cleanup;
    }

    printf("Read %d bytes data from server: '%s'\n", rv, buf);


cleanup:
    close(conn_fd);
}

两者实现交互通信之后的结果为:
在这里插入图片描述
在这里插入图片描述
       当运行服务器端的程序的时候,程序会阻塞,客户端连接上后就会给服务器端发送一个字符串,服务器端在收到这个字符串后会将这个字符串内容回射给客户端。*

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值