概述
文章目录
- 客户端client
- socket函数
- 定义结构体
- connect函数
- write函数
- read函数
- 服务器server
- socket函数调用
- 结构体servaddr
- bind函数
- listen函数
- accept函数
- 读写
- read函数
- write函数
客户端client
socket函数
头文件:
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
参数domain:
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
AF_NETLINK Kernel user interface device netlink(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_AX25 Amateur radio AX.25 protocol
AF_ATMPVC Access to raw ATM PVCs
AF_APPLETALK Appletalk ddp(7)
AF_PACKET Low level packet interface packet(7)
一般选用AF_INET(IPV4)
参数type:
SOCK_STREAM:TCP协议
SOCK_DGRAM:UDP协议
参数protocol:
会根据参数type自动选择,默认为0。
定义结构体
定义结构体servaddr以确定目的IP和端口
struct sockaddr_in servaddr;
如需定义ipv6则把sockaddr_in换成sockadddr_in6
之后利用定义的结构体确定目的IP和目的端口:
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET; //确定ipv4主机字节序
servaddr.sin_port = htons(port); //用htons函数把端口号变为网络字节序
inet_aton(sockip, &servaddr.sin_addr);//调用地址转换函数确定IP地址
connect函数
调用connect函数用以连接服务器
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数原型:
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
前面已经定义好带有端口号和IP的结构体servaddr,故只需将其带入connect函数中即可
参数const struct sockaddr *addr:
*addr型,填上servaddr,由于类型不匹配,需要强制类型转换,具体代码如下:
rv = connect(sockfd, (struct sockaddr *)&servaddr,
sizeof(servaddr));//调用可以连接服务器的connect函数
if( rv < 0 )
{
printf("Connect to server[%s:%d] failure:%sn",
sockip, port, strerror(errno));//如果调用失败打印出错
return -2;
}
printf("Connect to server[%s:%d] successfullyn",
sockip, port); //打印成功
write函数
write函数用以给服务器发送内容
头文件:
#include <unistd.h>
函数原型:
ssize_t write(int fd, const void *buf, size_t count);
参数fd直接带入sockfd,
参数*buf:给服务器发送的信息内容;
参数count:缓冲区大小
具体代码如下:
rv = write(sockfd, "Hello world", strlen("Hello world")); //往服务器写内容,
if( rv < 0 )
{
printf("Write to server by sockfd[%d] failure:%sn",
sockfd, strerror(errno));//打印出错原因,
break;
}
write函数和read函数需要包含在while(1)循环内
read函数
read函数用以接收读取服务器发送过来的内容。
头文件:
#include <unistd.h>
函数原型:
ssize_t read(int fd, void *buf, size_t count);
参数fd:直接带入sockfd
参数*buf:从服务器接收到的信息内容
参数count:缓冲区大小
具体代码如下:
rv = read(sockfd, buf, sizeof(buf));
if( rv < 0 )
{
printf("Read data from server by sockfd[%d] failure:%sn",
sockfd, strerror(errno));//调用失败,打印出错原因
break;
}
else if( rv == 0 )
{
printf("Socket[%d] get disconnectedn",
sockfd);
break;
}
else if( rv > 0 )
{
printf("Read %d bytes data from server :%sn",
rv, buf);//调用成功
}
write函数和read函数需要包含在while(1)循环内
值得注意的是,一般来说客户端先调用write函数,后调用read函数,而服务器相反,这样可以避免两边冲突,造成读取失败,下面会介绍服务器server代码的编写
服务器server
socket函数调用
与客户端类似,详见上文
结构体servaddr
端口号和协议与客户端类似,但由于服务器端不需要连接目的IP,而是需要容纳各个服务器的连接,因此在确定IP部分有区别于客户端代码,具体如下
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET; //确定 IPv4主机字节序
servaddr.sin_port = htons(port); //用 htons函数把端口号变为网络字节序
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
//确定服务器IP地址,htonl函数把客户端IP号变为网络字节序
bind函数
与客户端的connect函数类似,是用来连接客户端的函数
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数原型:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
将servaddr带入其中即可。
具体代码如下:
rv = bind(sockfd, (struct sockaddr *)&servaddr,
sizeof(servaddr));//调用bind函数
if( rv < 0 )
{
printf("Sockfd[%d] bind on port[%d] failure:%sn",
sockfd, port, strerror(errno)); //打印出错
return -2;
}
printf("Sockfd[%d] bind on port[%d] successfullyn",
sockfd, port); //打印成功
listen函数
调用listen函数监听端口,
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数原型:
int listen(int sockfd, int backlog);
参数backlog是指同时连接服务器的客户端个数,一般我们设置为13,
具体代码如下:
listen(sockfd, 13);
printf("Start to listen on port[%d]n", port);
//如果调用成功,则打印监听的端口
accept函数
accept函数用来处理与客户端的连接
头文件:
#include <sys/types.h>
#include <sys/socket.h>
函数原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数struct sockaddr *addr:需要重新定义一个结构体用来接收客户端的IP和端口信息
参数addrlen:需要定义一个socklen_t类型的值,
具体代码如下:
while(1)
{
struct sockaddr_in cliaddr; //定义接收客户端信息的结构体
socklen_t len;
clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
//定义一个clifd,来返回accept值,
if( clifd < 0)
{
printf("Accept new client failure:%sn",
strerror(errno));//函数调用错误,打印错误原因
continue;
return -3;
}
printf("Accept new client[%s:%d] successfullyn",
inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
//打印出接收到的客户端IP地址和端口号,
}
读写
注意:因为服务器要与客户端进行通信,故read函数和write函数对象都变成了clifd客户端,
read函数
服务器先调用read函数,再调用write函数,代码如下
rv = read(clifd, buf, sizeof(buf));
if( rv < 0 )
{
printf("Read data from server by sockfd[%d] failure:%sn",
sockfd, strerror(errno));//打印出错
close(clifd);
continue;
}
else if( rv == 0 )
{
printf("Socket[%d] get disconnectedn", sockfd);
close(clifd);
continue;
}
else if( rv > 0 )
{
printf("Read %d bytes data from server :%sn", rv, buf);
}
read代码是包含在accept函数之前的while(1)循环内的
write函数
具体用法见上文,代码如下
rv = write(clifd, MSG_FD, strlen(MSG_FD)); //往服务器写内容(MSG_FD)
if( rv < 0 )
{
printf("Write to server by sockfd[%d] failure:%sn",
sockfd, strerror(errno));//打印出错
close(clifd);
continue;
}
write代码是包含在accept函数之前的while(1)循环内的
最后
以上就是乐观手链为你收集整理的网络socket的编写和一些函数的运用的全部内容,希望文章能够帮你解决网络socket的编写和一些函数的运用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复