C语言学习笔记-网络与套接字

吃可爱长大的小学妹 提交于 2019-12-03 04:47:13

所有程序都需要编写检查错误的代码

一.基础知识

客户端与服务器之间将展开一段结构化对话,叫协议。

在C语言中,如果写一个与网络通信的程序,就需要新的数据流-套接字,套接字是双向的,既可以输入也可以输出

1.使用socket()函数创建一个套接字数据流

#include <sys/socket.h>

int xxxx = socket(PF_INET, SOCK_STREAM, 0);

xxxx是套接字名字

套接字与客户端程序通信,服务器需要经历,绑定端口,监听,接受连接,开始通信,四个阶段

服务启动时,服务器会为每项服务分配一个端口,服务器启动时,需要告诉操作系统将要使用哪个端口,这个过程叫做端口绑定。

2.这些代码将创建一个表示"互联网xxx端口"的套接字名

#include <arpa/inet.h>

struct sockeaddr_in xxxx;

xxxx.sin_family = PF_INET;

xxxx.sin+port = (in_port_t)htons(端口号);

xxxx.sin_addr.s_addr = htonl(INADDR_ANY);

int x = bind (套接字名字, (struct sockaddr * ) &xxxx, sizeof(name));

3.设置客户端连接服务器的排队数量

listen(套接字名字, xx)

xx为人数

在linux操作系统的/etc/services文件中可以查看常用服务使用的端口号

4.保存连接客户端的详细信息

struct sockaddr_storage xxxx;
unsigned int address_size = sizeof(client_addr);
int connect_d = accept(listener_d, (struct sockaddr *) &client_addr, &address_size);

套接字的输出方法:

二.使用send()函数写数据

send(套接字名称, xxxx, strlen(xxx), 0)

xxx和strlen(xxx)是消息和消息长度

0是高级参数填0即可

绑定端口有延时的解决办法,当使用某个端口绑定了套接字后,在接下来的30秒内,操作系统不允许任何程序绑定它,包括上次绑定这个端口的程序,我们在绑定前设置套接字的某个选项,就可以解决这个问题了。

int reuse = 1;

setsockopt(套接字名字, SQL_SOCKET, SO_REUSEADDR, (char * )&reuse, sizeof(int));

三.使用recv()函数读数据

recv (接收的描述符,字符变量的缓冲区,<要读取几个字节>, 0);

1.字符串不以\0结尾

2.当用户在客户端输入文本时用\r\n结尾

3.recv()将返回字符个数,如果发生错误就返回-1,如果客户端关闭连接就返回0

4.recv调用不一定能一次接收所有字符,需要配合循环,读取字符。

例如:

int read_in (int socket, char * buf, int len)

{

int c = recv(socket, buf, len, 0);

}

四.为每个客服端复制一份子进程

服务器在运行一份套接字进程给第一个用户时,无法运行第二个进程给第二个用户,因此使用fork()为每个用户创建一个子进程。

服务器父进程只需要用主监听套接字,因此关闭副套接字,子进程需处理副套接字,关闭主监听套接字

五.创建ip地址套接字

1.客户端套接字的创建:

int xxx = socket (PF_INET, SOCK_STREAM, 0);

2.客户端和服务器处理套接字的方法不同,服务器会把套接字绑定到本地端口,而客户端会把套接字连接至远程端口。

struct sockaddr_in xxx;

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

xxx.sin_family = PF_INET;

xxx.sin_addr.s_addr = inet_addr("ip地址");

xxx.sin_port = htons(端口号);

connect(xxx, (struct sockaddr *) &xxx, sizeof(xxx)); 连接套接字至远程端口

六.使用域名创建套接字

域名系统,计算机发送数据包时需要在地址一栏填写数字形式的ip地址,而dns可以把域名转化为ip地址

创建域名套接字:

#include<netdb.h>

struct addrinfo * xxx;

struct addrinfo xxxx;

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

xxxx.ai_family = PF_UNSPEC;

xxxx.ai_socktype = SOCK_STREAM;

getaddrinfo("域名", "端口", &xxxx, &xxx);

getaddrinfo会在堆上创建一个xxx名字的新数据结构给定域名和端口号。

随后创建套接字

int x = socket(xxx->ai_family, xxx->ai_socktype, xxx->ai_protocal);

connect(x, xxx->ai_addr, xxx->ai_addrlen);

freeaddrinfo(xxx);连接以后删除地址数据

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!