c语言 socket网络编程

引用图片了解客户端、服务器基本架构

连接图

一、socket函数(创建一个新的socket)

1.头文件:

#include <sys/types.h>
#include <sys/socket.h>

2.函数原型:

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

3.参数:

1)通信协议

AF_INET Ipv4 网络协议
AF_INET6 Ipv6 网络协议

2)通信类型

1、SOCK_STREAM 提供双向连续且可信赖的数据流, 即TCP. 支持 OOB 机制, 在所有数据传送前必须使用connect()来建立连线状态.
2、SOCK_DGRAM 使用不连续不可信赖的数据包连接
3、SOCK_SEQPACKET 提供连续可信赖的数据包连接
4、SOCK_RAW 提供原始网络协议存取
5、SOCK_RDM 提供可信赖的数据包连接

3) 一般设为零

4.返回值:成功返回socket套接字的网络标识符,失败则返回-1。

二、bind函数(绑定端口号、IP地址)

1.头文件:#include<sys/socket.h>

2.函数原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

3.参数:

1)网络描述符(既是socket函数创建成功的返回值)

2)第二个参数是一个指向特定协议的地址结构的指针

结构体名: sockaddr_in
头文件:#include<linux/in.h>
结构体成员1:sin_family(通信协议一般IPV4为AF_INET)。
结构体成员2:sin_ port(端口号)(需要用到主机端口号转网络传输方式函数–htons)。
结构体成员3:struct in_addr sin_addr(又是一个结构体)(配置网络IP地址)(需要用到inet_aton函数–网络的阿斯克码转网络传输方式)。

3)第三个参数是地址结构体的长度

4.返回值:成功返回0,失败返回-1,发送错误信息。

三、listen函数(监听)

1.头文件:

#include <sys/types.h>
#include <sys/socket.h>

2.函数原型:int listen(int sockfd, int backlog);

3.参数:

1)网络标识符(既是socket函数的成功调用的返回值)

2)承载量(表示最多可同时监听的数量)

4.返回值:成功返回0,失败返回-1,并且返回错误信息

四、accept函数(等待连接,运行时阻塞至客户端成功接入)

1.头文件:

#include <sys/types.h>
#include <sys/socket.h>

2.函数原型:

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

3.参数:

1)网络标识符(同上)

2)结构体指针(保存连接的网络信息)

3) 结构体的长度

4.返回值:成功返回接入网络的客户端网络标识符,失败返回-1,返回错误信息。

五、connect函数(客户端接入服务器函数)

1.头文件:

#include <sys/types.h>
#include <sys/socket.h>

2.函数原型:

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

3.参数:

1)网络标识符(客户端成功调用socket函数的返回值)

2)结构体指针(保存连接的网络信息)

3) 结构体的长度

4.返回值:成功返回接入0,失败返回-1,返回错误信息。

六、 连接成功后可用read、write函数进行数据的收发,read、write函数使用见文件编程基础

七、服务器、客户端小程序代码展示

服务器代码

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
    int s_fd;
    int c_fd;
    int n_read;
    char readBuf[128];
    char writeBuf[128];
    int n_write;
    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;
    memset(&s_addr, 0, sizeof(struct sockaddr_in));
    memset(&c_addr, 0, sizeof(struct sockaddr_in));
    // socket
    s_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s_fd == -1) {
        perror("socket");
        exit(-1);
    }
    // init struct sockaddr_in
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(argv[1]));
    inet_aton("192.168.81.129", &s_addr.sin_addr);
    // bind
    bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
    // listen
    listen(s_fd, 10);
    // accept
    // int c_fd = accept(s_fd,(struct sockaddr *)&c_addr,(unsigned
    // *)sizeof(struct sockaddr_in));
    int c_len = sizeof(struct sockaddr_in);
    while (1) {
        c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &c_len);
        // why???
        if (c_fd == -1) {
            perror("accept");
            exit(-1);
        }
        printf("connected to IP: %s\n", inet_ntoa(c_addr.sin_addr));

        if (fork() == 0) {
            if (fork() == 0) {
                while (1) {
                    printf("input: \n");
                    memset(writeBuf, 0, 128);
                    gets(writeBuf);
                    n_write = write(c_fd, writeBuf, strlen(writeBuf));
                    if (n_write == -1) {
                        perror("write");
                    }
                }
            }
            while (1) {
                memset(readBuf, 0, 128);
                n_read = read(c_fd, readBuf, 128);
                if (n_read == -1) {
                    perror("read");
                } else {
                    printf("client message: %s\n", readBuf);
                }
            }
        }
    }
    return 0;
}

客户端代码

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
    int c_fd;
    int n_read;
    char readBuf[128];
    char writeBuf[128];
    struct sockaddr_in c_addr;
    memset(&c_addr, 0, sizeof(struct sockaddr_in));
    // socket
    c_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (c_fd == -1) {
        perror("socket");
        exit(-1);
    }
    // init struct sockaddr_in
    c_addr.sin_family = AF_INET;
    c_addr.sin_port = htons(atoi(argv[1]));
    inet_aton("192.168.81.129", &c_addr.sin_addr);

    int r_con =
        connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr));
    if (r_con == -1) {
        perror("connect");
    }
    while (1) {
        printf("input: \n");
        memset(writeBuf,0,128);
        gets(writeBuf);
        write(c_fd, writeBuf, strlen(writeBuf));

        if (fork() == 0) {
            while (1) {
                memset(readBuf,0,128);
                n_read = read(c_fd, readBuf, 128);
                if (n_read == -1) {
                    perror("read");
                } else {
                    printf("Server Message: %s\n", readBuf);
                }
            }
        }
    }

    return 0;
}
  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux Socket服务器端编程实例 例:建立一个Linux TCP服务器,等待客户端的连接请求,一旦接收到客户端请求,将客户端的IP地址和端口号打印出来,并且向客户端发送"Hello!Socket communication world!"字符串,然后关闭服务器。 0 Linux-Socket-服务器编程实例全文共13页,当前为第1页。 Linux Socket服务器端编程实例 Socket服务器编程中的头文件 #include<stdlib.h> stdlib 头文件即standard library标准库头文件。 该文件包含了的C语言标准库函数的定义,常用的函数如malloc()、calloc()、realloc()、free()、system()、atoi()、atol()、rand()、srand()、exit()等等。 1 Linux-Socket-服务器编程实例全文共13页,当前为第2页。 Linux Socket服务器端编程实例 #include<stdio.h> stdio 就是指 "standard input & output"(标准输入输出),所以,源代码中如用到标准输入输出函数时,就要包含这个头文件! 例如c语言中的 printf("%d",i); scanf("%d",&i);等函数。 2 Linux-Socket-服务器编程实例全文共13页,当前为第3页。 Linux Socket服务器端编程实例 #include<errno.h> 提供错误号errno的定义。查看错误代码errno是调试程序的一个重要方法。当linux C api函数发生异常时,一般会将errno变量(需include errno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因。 3 Linux-Socket-服务器编程实例全文共13页,当前为第4页。 Linux Socket服务器端编程实例 #include<string.h> string.h是预先定义好的函数库头文件,里面定义了一些字符串函数,如bzero等,添加这个头文件后才可以使用和字符串相关的操作函数 4 Linux-Socket-服务器编程实例全文共13页,当前为第5页。 Linux Socket服务器端编程实例 #include<netdb.h> Unix和Linux特有的头文件,主要定义了与网络有关的结构、变量类型、宏、函数等。所以在进行Socket网络编程时,必须要包含这个头文件。 5 Linux-Socket-服务器编程实例全文共13页,当前为第6页。 Linux Socket服务器端编程实例 #include<sys/types.h> 在应用程序源文件中包含 <sys/types.h> 以访问 整型、长整型和指针数据模型的定义。所有这些类型在 32位编译环境中保持为 32 位值,并会在64位编译环境中增长为 64 位值。 6 Linux-Socket-服务器编程实例全文共13页,当前为第7页。 Linux Socket服务器端编程实例 #include<netinet/in.h> 数据结构sockaddr_in就定义在这个头文件中。 #include<sys/socket.h> 这个头文件提供socket函数及相关数据结构 7 Linux-Socket-服务器编程实例全文共13页,当前为第8页。 Linux Socket服务器端编程实例 main函数中的参数 在Linux C语言中,main函数通常写作以下形式: int main(int argc,char *argv[]) 其中的两个参数argc和*argv[]是什么含义呢? 8 Linux-Socket-服务器编程实例全文共13页,当前为第9页。 Linux Socket服务器端编程实例 argc:命令行总的参数的个数,即argv中元素的个数。 *argv[ ]:字符串数组,用来存放指向字符串参数的指针数组,每一个元素指向一个参数。 9 Linux-Socket-服务器编程实例全文共13页,当前为第10页。 Linux Socket服务器端编程实例 argv[0]:指向程序的全路径名。 argv[1]:指向在DOS命令行中执行程序名后的第一个字符串。 argv[2]:指向第二个字符串。 … … 10 Linux-Socket-服务器编程实例全文共13页,当前为第11页。 Linux Socket服务器端编程实例 比如编译好的程序为my.exe 在命令行执行 my.exe 1 2 3 那argc就是4,argv[0]是"my.exe",argv[1]是"1",argv[2]是"2",argv[3]是"3"; 11 Linux-Socket-服务器编程实例全文共13页,当前
客户端: #include #include // 包含套接字函数库 #include #include // 包含AF_INET相关结构 #include // 包含AF_INET相关操作的函数 #include #include #include #define PORT 6789 #define IP_ADDR "127.0.0.1" #define SIZE 10240 int main() { struct tm *timeptr; time_t timeval; //时间变量 char tm[50]; int sockfd; // 用于保存客户套接字标识符 int len; // 用于客户消息长度 struct sockaddr_in address; // 定义客户套接字地址结构体 int result; sockfd = socket(AF_INET,SOCK_STREAM, 0); // 定义套接字类型 address.sin_family = AF_INET; // 定义套接字地址中的域 address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_addr.s_addr = inet_addr(IP_ADDR); // 定义套接字地址 address.sin_port = htons(PORT); // 定义套接字端口 char buf[100]; // 定义要传送的消息 memset(buf,0,100); char str[90]; //存贮输入的语句 char shmaddr[SIZE]; //接受服务器发送的全部聊天数据 int i=0; char myname[100]; char say[10]={"说:"}; printf("欢迎来到聊天室,请输入你的姓名:"); scanf("%s",myname); len = sizeof(address); result = connect(sockfd, (struct sockaddr *) &address, len); // 请求连接 if (result == -1) { perror("Connect failed"); return 1; } printf("%s成功登录服务器:\n",myname); pid_t pid; pid=fork(); if(pid==-1) { printf("fork failed"); } int sendbytes=0; if(pid==0) //子进程用于发送数据 { while(1) { scanf("%s",str); (void)time(&timeval); strcpy(tm,ctime(&timeval)); strcpy(buf,myname); //姓名传入buf中 strcat(buf,":"); strcat(buf,str); strcat(buf," ["); strc

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值