TCP套接字

TCP套接字

1、Server

1、创建套接字,和地址族

int sockFd;
int newSock;//用于接收客户端请求

struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr; /* 接受客户端地址族的结构体对象 */

2、编写服务器地址族

sockFd = socket(AF_INET, SOCK_STREAM, 0);//PF_INET == AF_INET
memset(&serverAddr, 0, sizeof(struct sockaddr_in));

serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* s_addr是宏定义, s_addr = S_un.S_addr */
serverAddr.sin_port = htons(8090);	//最好采用宏定义方便修改 #define SERVER_PORT 8090
/*  
字节序转换函数
htonl: 转换long类型到网络字节序

htons: 转换short类型到网络字节序

ntohl: 转换网络字节序到long类型

ntohs: 转换网络字节序到short类型

inet_addr: 将字符串格式IP转换到网络字节序

inet_ntoa: 将网络字节序格式IP转换到字符串
*/ 

3、绑定地址族

/* 最好加个判断 */
if(bind(sockFd, (struct sockaddr*)&serverAddr, sizeof(sockaddr_in) == -1)
{
	//需要头文件 <errno.h> 或者直接打印,方便查看哪出的问题
	fprintf(stderr, "Bind error: %s\a\n", strerror(errno));
	exit(1);
}

4、监听

if (listen(sockfd, 8) == -1) 
{ 
	fprintf(stderr, "Listen error: %s\n\a", strerror(errno));
	exit(1);
} 

了解更多backlog可以点我
5、接受

socklen_t size = sizeof(struct sockaddr_in); /* socklen_t与int 大小一致*/
if((newSock = accept(sockFd, (struct sockaddr *)(&clientAddr), &size)) == -1)
{
	fprintf(stderr, "Accept error: %s\a\n", strerror(errno)); 
	exit(1); 
}

6、读写

char buf[1024] = {0};
read(newSock, buf, sizeof(buf));
write(newSock, buf, sizeof(buf));

int recv(int sockfd,void *buf,int len,int flags)
int send(int sockfd,void *buf,int len,int flags)

前面的三个参数和read,write相同,第四个参数能够是0或是以下的组合
0表示与read,write相同的操作,即查看数据并从系统缓冲区移走数据
MSG_DONTROUTE:不查找路由表
MSG_OOB:接受或发送带外数据
MSG_PEEK:查看数据,并不从系统缓冲区移走数据
MSG_WAITALL :等待任何数据
****************************************************************************************************************
MSG_DONTROUTE:是send函数使用的标志.这个标志告诉IP协议.目的主机在本地网络上面,
没有必要查找路由表.这个标志一般用网络诊断和路由程式里面。
MSG_OOB:表示能够接收和发送带外的数据.
MSG_PEEK:是recv函数的使用标志,表示只是从系统缓冲区中读取内容,而不清除系统缓冲区的
内容。这样下次读的时候,仍然是相同的内容。一般在有多个进程读写数据时能够使用这个标志。
MSG_WAITALL:是recv函数的使用标志,表示等到任何的信息到达时才返回。使用这个标志的时候
recv会一直阻塞,直到指定的条件满足,或是发生了错误。
1)当读到了指定的字节时,函数正常返回,返回值等于len
2)当读到了文档的结尾时,函数正常返回.返回值小于len 3)当操作发生错误时,返回-1,且配置错误为相应错误号(errno)

7、关闭

close(newSock);

int shutdown(int sockfd,int howto)
TCP连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个向,这个时候我们能够使用shutdown.针对不同的howto,系统回采取不同的关闭方式.
howto=0这个时候系统会关闭读通道.但是能够继续往接字描述符写.
howto=1关闭写通道,和上面相反,着时候就只能够读了.
howto=2关闭读写通道,和close相同在多进程程式里面,假如有几个子进程共享一个套接字时,假如我们使用shutdown, 那么任何子进程都不能够操作了,这个时候我们只能够使用close来关闭子进程的套接字描述符.

2、Client

1、创建套接字

int client_sock;
struct sockaddr_in server_addr;

client_sock = socket(AF_INET, SOCK_STREAM, 0);

2、创建服务器地址族

memset(&server_addr, 0, sizeof server_addr);

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8090);
server_addr.sin_addr.s_addr = inet_addr(127.0.0.1);
/* 127.0.0.1 本地IP回环*/

3、连接

if (connect(client_sock, (struct sockaddr *)(&server_addr),sizeof server_addr) == -1)
{
	fprintf(stderr, "Connect Error: %s\a\n", strerror(errno));
	exit(1);
}

4、读写

char buf[1024] = {0};
read(newSock, buf, sizeof(buf));
write(newSock, buf, sizeof(buf));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值