socket相关函数

本文详细介绍了套接字(socket)的相关函数,包括服务器端的socket、bind、listen、accept和客户端的socket、connect,以及send、recv等通信函数。socket函数用于创建套接字描述符,bind将IP地址和端口号绑定到socket,listen开始监听客户端连接,accept接收客户端请求并建立新的连接描述符,connect则是客户端发起连接,最后recv和send实现数据的发送和接收。
摘要由CSDN通过智能技术生成

套接字socket:
服务器(6)
socket 
bind(绑定)    
listen(监听客户端,)
accept(接收)    
send     
recv

客户端(4)
socket    
connect (发起连接时,端口号要保持一致)     
send     
recv

1、socket函数
int socket(int domain,int type,int protocol);

socket函数用于创建一个socket描述符,它是唯一表示标识一个
socket,   sockfd

domain:叫做协议族/协议域。
常用的协议族有AF_INET(决定了要用IP v地址与端口号的组合),
AF_INET6,AF_LOCAL等等,协议族决定了socket的地址类型。

type:是指定socket的类型。常用的是:
SOCK_STREAM(流式套接字,使用的是TCP协议);
SOCK_DGRAM(数据包套接字,使用的是UDP协议);

protocol: 指定协议,通常情况下写成0即可

当我们调用了socket创建一个socket的时候,返回sockfd,并没有一个
具体的地址,如果我们想给socket赋值一个地址的话,我们必须调用
bind()函数,否则,调用listen()connect()函数时,系统会自动随机分配
一个端口


2、bind()绑定
bind()函数就是把地址族中的特定地址赋值给socket,
AF_INET就是把IP v4的地址和端口号赋值给了socket,
int bind(int sockfd,const struct sockaddr * my_addr,socklen_t addrlen);

sockfd:socket描述字符,是通过socket函数创建的,bind()函数就是
给这个描述字绑定一个名字。
addr:是指向要绑定给sockfd的协议地址
addrlen:对应是地址的长度

出现无法绑定的问题:
setsockopt:函数的用处就是解决套接字绑定失败。
int setsockopt(int s,int level,int optname,const void* optval,socklen_t optlen);
s:标识的是一个套接字的描述符
level:选项定义的层次,SOL_SOCKET,IPPROTO_TCP
optname:
optval:指向的是存放选项值的缓冲区
optlen:

3、listen()监听-----服务器使用,用于监听sockfd
int listen(int sockfd,int backlog);
listen(sockfd,5);在监听队列里放5个客户端,并不代表总共只能监听5个客户端
backlog:相应的socket可以排列的最大链接数。

4、connect()连接------只用于客户端,来连接服务器
int connect(int sockfd,const struct sockaddr * serv_addr,socklen_t addrlen)
sockfd:就是客户端的socket描述字
serv_addr:服务器的socket地址
addrlen:socket地址的长度

5、accept()
int accept(int sockfd,const struct sockaddr * addr,socklen_t *addrlen)
TCP服务器调用socket(),bind(),listen()
TCP客户端依次调用socket(),connect(),
TCP服务器监听到这个客户端的连接请求后,就会调用accept()函数来接收请求,
这样连接就建立完成。
sockfd:服务器的socket描述字
addr:用于返回客户端的协议地址,
addrlen:这个协议地址的长度?为什么是指针
当accept成功之后,返回值就是会长生一个新的描述字,代表客户端连接服务器成功。


6、    read()从fd中读取数据,write()写数据
    recv()  send()
    recvfrom()     sendto()

服务器端:

 

 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

#define PORT     8888

int main()
{
	int sockfd, ret;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;

	sockfd = socket(PF_INET, SOCK_STREAM, 0);
	if (-1 == sockfd)
	{
		perror("socket");
		exit(1);
	}

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");

	ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if (-1 == ret)
	{
		perror("bind");
		exit(1);
	}

	ret = listen(sockfd, 5);
	if (-1 == ret)
	{
		perror("listen");
		exit(1);
	}

	int fd[1000] = {0};
	int MaxFd, i = 0, j;
	fd_set ReadFd, tmpfd;
	char buf[32] = {0};
	int length = sizeof(client_addr);

	FD_ZERO(&ReadFd);
	FD_SET(sockfd, &ReadFd);
	MaxFd = sockfd;

	while (1)
	{
		tmpfd = ReadFd;
		ret = select(MaxFd + 1, &tmpfd, NULL, NULL, NULL);
		if (-1 == ret)
		{
			perror("select");
		}

		if (FD_ISSET(sockfd, &tmpfd))    //有客户端发起连接
		{
			for (j = 0; j < i; j++)
			{
				if (fd[j] == 0)
				{
					break;
				}
			}
			fd[j] = accept(sockfd, (struct sockaddr *)&client_addr, &length);
			if (-1 == fd[j])
			{
				perror("accept");
			}
			printf("accept client %d port %d\n", fd[j], client_addr.sin_port);
			if (MaxFd < fd[j])
			{
				MaxFd = fd[j];
			}
			FD_SET(fd[j], &ReadFd);
			if (j == i)
			{
				i++;
			}
		}
		else                            //有客户端发消息
		{
			for (j = 0; j < i; j++)
			{
				if (FD_ISSET(fd[j], &tmpfd))
				{
					ret = recv(fd[j], buf, sizeof(buf), 0);
					if (-1 == ret)
					{
						perror("recv");
					}
					if (!strcmp(buf, "bye"))
					{
						close(fd[j]);
						FD_CLR(fd[j], &ReadFd);   //从集合里面清除
						fd[j] = 0;  
						break;
					}
					printf("%s\n", buf);
					memset(buf, 0, sizeof(buf));

					break;
				}
			}
		}
			
	}

	return 0;
}

客户端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

#define PORT    8888

int sockfd;

void StopClient(int num)  //进程收到SIGINT信号,退出
{
	send(sockfd, "bye", strlen("bye"), 0);
	close(sockfd);
	printf("BYE!\n");
	exit(1);
}

int main()
{
	int ret;
	struct sockaddr_in server_addr;

	signal(SIGINT, StopClient);

	sockfd = socket(PF_INET, SOCK_STREAM, 0);
	if (-1 == sockfd)
	{
		perror("socket");
		exit(1);
	}

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
	ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if (-1 == ret)
	{
		perror("connect");
		exit(1);
	}

	char buf[32] = "helloworld";
	while (1)
	{
		ret = send(sockfd, buf, strlen(buf), 0);
		if (-1 == ret)
		{
			perror("send");
			exit(1);
		}
		sleep(1);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值