Linux下的TCP Socket通讯

1、socket函数sql

一、头文件:数据库

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

#include <sys/socket.h>网络

二、函数原型:dom

int socket(int domain, int type, int protocol);socket

socket函数相似于open,用来打开一个网络链接,若是成功则返回一个网络文件描述符(int类型),以后咱们操做这个网络链接都经过这个网络文件描述符。tcp

dimain:域,网络域,网络地址范围(IPV4或IPV6等),也就是协议簇函数

type:指定套接字类型:SOCK_STREAM(TCP网络)、SOCK_DGRAM(UDP)、SOCK_SEQPACKETspa

protocol:指定协议,若是指定0,表示使用默认的协议server

三、函数形参:

3.一、domain:(域)

AF_INET      ip
AF_INET6    ipv6

AF_PACKET         packet         低级数据包接口

PF_PACKET   不懂,待了解

PF_INET      待了解(AF开头的表示地址族,PF开头的表示协议族,协议族包含多个地址族,可是当前这种还从未实现,而在<sys/socket.h>中PF的值老是与AF的值相等的)

3.二、type:(套接字类型):

SOCK_RAW      原始套接字     ——>使用原始套接字时候调用,原始套接字也就是链路层协议

SOCK_STREAM    字节流套接字    ——>提供顺序,可靠,双向,基于链接的字节流。 能够支持带外数据传输机制。例如:TCP协议、FTP协议

SOCK_DGRAM         数据报套接字    ——>支持数据报(无链接,不可靠的固定最大长度的消息)例如:UDP协议

SOCK_SEQPACKET   有序分组套接字    ——>为固定最大长度的数据报提供有序,可靠,双向链接的数据传输路径; 消费者须要利用每一个输入系统调用读取整个分组

3.三、protocol(协议):

IPPROTO_IP       IP传输协议

IPPROTO_TCP      TCP传输协议

IPPROTO_UDP       UDP协议

IPPROTO_SCTP      SCTP传输协议

IPPROTO_ICMP          ICMP协议

IPPROTO_IGMP      IGMP协议

通常状况下IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP协议用的最多,UDP协议protocol就取IPPROTO_UDP,TCP协议protocol就取IPPROTO_TCP;通常状况下,咱们让protocol等于0就能够,系统会给它默认的协议。可是要是使用raw socket协议,protocol就不能简单设为0,要与type参数匹配.

四、返回值:

成功时返回一个小的非负整数值,他与文件描述符相似,咱们称为套接字描述符,简称sockfd。失败,则返回-1。

五、例子:

/*---------------------建立一个监听socket-------------------*/

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)

    {

        perror("socket() error\n");

        exit(1);

}

2、bind函数

一、头文件:

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

二、函数原型:

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

服务端套接字绑定本身的IP地址与端口号,客户端那边能够不写,内核会给它分配一个临时的端口。

三、函数形参:

3.一、sockfd:服务器或者客户端本身建立的socket

3.二、addr:服务器或者客户端本身的地址信息(协议族、IP、端口号)

3.三、addrlen:服务器或者客户端本身的地址信息的长度

四、返回值:

绑定成功,返回0,失败返回-1

五、例子:

    /*---------------------绑定IP和端口bind----------------------*/

    bzero(&server, sizeof(server));

    server.sin_family = AF_INET;

    server.sin_port = htons(port);

    server.sin_addr.s_addr = inet_addr(ip);

 

    if (bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1)

    {

        perror("bind() error\n");

        exit(1);

    }

3、connect函数

一、头文件:

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

二、函数原型:

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

TCP客户端经过connect函数与服务端链接,进行通讯。

三、函数形参:

3.一、sockfd(客户端本身建立的sock)

3.二、addr(服务端地址族、服务端IP地址、服务端端口号)

3.三、addrlen(服务端地址字节长度)

四、返回值:

链接成功,返回0,链接失败,返回-1

五、例子:

struct sockaddr_in client;

addrlen = sizeof(client);

        if ((connetfd = accept(listenfd, (struct sockaddr *)&client, &addrlen)) == -1)

        {

            perror("accept() error\n");

            exit(1);

        }

接下来给出一个大例子,tcp——socket套接字通讯,结合sqlite3数据库操做

#include <stdio.h>

#include <stdlib.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <unistd.h>

#include <string.h>

 

int main()

{

    struct sockaddr_in server;

    struct sockaddr_in client;

    int listenfd, connetfd;

    char ip[20];

    int port;

    int addrlen;

    char rebuf[100];

    char wrbuf[100];

    char tmp[100];

    int revlen;

    /*---------------------建立一个监听socket-------------------*/

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)

    {

        perror("socket() error\n");

        exit(1);

    }

 

    /*----------------------输入要监听的IP和端口----------------------*/

    printf("Please input the ip:\n");

    scanf("%s", ip);

    printf("Please input the port:\n");

    scanf("%d", &port);

 

    /*---------------------绑定IP和端口bind----------------------*/

    bzero(&server, sizeof(server));

    server.sin_family = AF_INET;

    server.sin_port = htons(port);

    server.sin_addr.s_addr = inet_addr(ip);

 

    if (bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1)

    {

        perror("bind() error\n");

        exit(1);

    }

    /*----------------------开始监听listen-------------------*/

    if (listen(listenfd, 20) == -1)

    {

        perror("listen() error\n");

        exit(1);

    }

    int client_pid = 0;

    while (1)

    {

        /*----------------------accept------------------*/

        addrlen = sizeof(client);

        if ((connetfd = accept(listenfd, (struct sockaddr *)&client, &addrlen)) == -1)

        {

            perror("accept() error\n");

            exit(1);

        }

        /*---------------------show client---------------*/

        printf("connect successful!\n");

        printf("the client ip is %s,port is %d\n", inet_ntoa(client.sin_addr), ntohs(port));

        client_pid = fork();

        if (client_pid == 0)

        {

            //子进程

            close(listenfd); //关闭监听请求

            /*----------------------read and write----------*/

            int serial = 0;

            while (1)

            {

                bzero(rebuf, sizeof(rebuf));

                revlen = read(connetfd, rebuf, sizeof(rebuf));

                if ((memcmp("bye", rebuf, 3)) == 0)

                {

                    printf("Bye-bye then close the connect...\n");

                    break;

                }

                bzero(wrbuf, sizeof(wrbuf));

                bzero(tmp, sizeof(tmp));

                sprintf(tmp, "%d", serial);

                strcat(tmp, rebuf);

                bcopy(tmp, wrbuf, strlen(tmp));

                write(connetfd, wrbuf, sizeof(wrbuf));

                rebuf[revlen] = '\0';

                printf("the info from client is:%s\n", rebuf);

                serial++;

            }

            return 0;

        }

        close(connetfd); //父进程关闭链接请求

    }

    return 0;

}

相关文章
相关标签/搜索