Linux系统c语言socket实现TCP通信

⌚Time: 2023-05-21 23:31:14

👨‍💻Author: Jack Ge

socket通信用到的函数


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

af:一个地址描述。仅支持AF_INET格式,也就是说ARPA Internet地址格式。

type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。

protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

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

int listen(int sockfd, int backlog);

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

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

read()/write()

recv()/send()

readv()/writev()

recvmsg()/sendmsg()

recvfrom()/sendto()

int close(int fd);

sockaddr_in结构体(在netinet/in.h中定义)


struct sockaddr_in

 

{

 

short sin_family;/*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/

 

unsigned short sin_port;/*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/

 

struct in_addr sin_addr;/*IP address in network byte order(Internet address)*/

 

unsigned char sin_zero[8];/*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/

 

};

对于服务端

注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。


#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <sys/socket.h>



int main(){

    //创建套接字

    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //将套接字和IP、端口绑定

    struct sockaddr_in serv_addr;

    memset(&serv_addr, 0, sizeof(serv_addr));//每个字节都用0填充

    serv_addr.sin_family = AF_INET;//使用IPv4地址

    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务端IP地址

    serv_addr.sin_port = htons(1234);//端口

    bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));//绑定

    //进入监听状态,等待用户发起请求

    listen(serv_sock, 20);

    //接收客户端请求

    struct sockaddr_in clnt_addr;

    socklen_t clnt_addr_size = sizeof(clnt_addr);

    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

    //收发数据

    char buffer[1024] = {0};

    read(clnt_sock, buffer, sizeof(buffer)-1);

    printf("Message from client:%s\n",buffer);



    char str[] = "hello client";

    write(clnt_sock, str, sizeof(str));



    //关闭套接字

    close(clnt_sock);

    close(serv_sock);



    return 0;

}

对于客户端


#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <sys/socket.h>



int main(){

    //创建套接字

    int sock = socket(AF_INET, SOCK_STREAM, 0);

    //向服务器(特定的IP和端口)发起请求

    struct sockaddr_in serv_addr;

    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    serv_addr.sin_port = htons(1234);

    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    //收发数据

    char str[] = "hello from client";

    write(sock, str, sizeof(str));



    char buffer[1024] = {0};

    read(sock, buffer, sizeof(buffer)-1);

    printf("Message from server:%s\n",buffer);

    //关闭套接字

    close(sock);



    return 0;



}