一、socket函数
1、头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
2、函数原型:
int socket(int domain, int type, int protocol);
socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。
dimain:域,网络域,网络地址范围(IPV4或IPV6等),也就是协议簇
type:指定套接字类型:SOCK_STREAM(TCP网络)、SOCK_DGRAM(UDP)、SOCK_SEQPACKET
protocol:指定协议,如果指定0,表示使用默认的协议
3、函数形参:
3.1、domain:(域)
AF_INET ip
AF_INET6 ipv6
AF_PACKET
packet 低级数据包接口
PF_PACKET 不懂,待了解
PF_INET 待了解(AF开头的表示地址族,PF开头的表示协议族,协议族包含多个地址族,但是当前这种还从未实现,而在<sys/socket.h>中PF的值总是与AF的值相等的)
3.2、type:(套接字类型):
SOCK_RAW 原始套接字 ——>使用原始套接字时候调用,原始套接字也就是链路层协议
SOCK_STREAM 字节流套接字
——>提供顺序,可靠,双向,基于连接的字节流。 可以支持带外数据传输机制。例如:TCP协议、FTP协议
SOCK_DGRAM 数据报套接字 ——>支持数据报(无连接,不可靠的固定最大长度的消息)例如:UDP协议
SOCK_SEQPACKET 有序分组套接字 ——>为固定最大长度的数据报提供有序,可靠,双向连接的数据传输路径; 消费者需要利用每个输入系统调用读取整个分组
3.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参数匹配.
4、返回值:
成功时返回一个小的非负整数值,他与文件描述符类似,我们称为套接字描述符,简称sockfd。失败,则返回-1。
5、例子:
/*---------------------创建一个监听socket-------------------*/
if ((listenfd =
socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket() error\n");
exit(1);
}
二、bind函数
1、头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
2、函数原型:
int bind(int sockfd, const struct sockaddr *addr,socklen_t
addrlen);
服务端套接字绑定自己的IP地址与端口号,客户端那边可以不写,内核会给它分配一个临时的端口。
3、函数形参:
3.1、sockfd:服务器或者客户端自己创建的socket
3.2、addr:服务器或者客户端自己的地址信息(协议族、IP、端口号)
3.3、addrlen:服务器或者客户端自己的地址信息的长度
4、返回值:
绑定成功,返回0,失败返回-1
5、例子:
/*---------------------绑定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);
}
三、connect函数
1、头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
2、函数原型:
int connect(int sockfd, const struct sockaddr
*addr,socklen_t addrlen);
TCP客户端通过connect函数与服务端连接,进行通信。
3、函数形参:
3.1、sockfd(客户端自己创建的sock)
3.2、addr(服务端地址族、服务端IP地址、服务端端口号)
3.3、addrlen(服务端地址字节长度)
4、返回值:
连接成功,返回0,连接失败,返回-1
5、例子:
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;
}
原文地址:https://www.cnblogs.com/GotWindy/p/11066976.html