socket 网络编程编程
复习了两天的socket网络编程,打算做个总结,学过看过网络通信技术相关书籍就知道网络通信的的基础,TCP/IP为一组协议族,有两种模型结构为OSI模型及其简化模型tcp/ip模式,OSI模型多了两层分别为会话层,和表示层, tcp/ip模型有五层,应用层,传输层,网络层,数据链路层,及物理层。应用层协议有telent,和ftp,http等,网络层为ip协议,传输层有主要有两种传输协议,tcp和udp传输两种,两种各有优缺点,tcp可靠,但是效率低,udp高效率,但不可靠,要使用须得根据具体情况而定,至于其他层打算要是忘记了打算让自己看书即可,应用程的一般都是写好了的应用程序,我们只需要进行相应的移植与安装即可,可以去研究源码。
经观察发现tcp的传输模型与udp传输模型只有一小点区别,一个是链接的,一个是不链接的,socket编程一般要用到以下几个函数,编程直接套用即可。
服务端:
第一步:
socket( int af, int type, int protocol)函数有三个参数:
af:一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。
type:新套接口的类型描述。 ,一般用SOCK_STREAM表示双向直接流,前提是必须处于链接状态,一般用于tcp,udp用SOCK_DGRAM
protocol:套接口所用的协议。如调用者不想指定,可用0指定,表示缺省。
其次函数带返回值,可以用以判断是否创建字节流创建成功,如果大于0其返回值作为connect函数的第一个入口参数值
第二步:在链接客户端发起链接访问之前创立struct sockaddr_in address address结构;其重要成员如下
address. sin_family这个参数一般为AF_INET,与socket函数的第一个参数一样,表示ip类为ipv4;
address.sin_addr.s_addr 这个为服务器地址,一般客户端设置成服务器地址,服务端设置成0.0.0.0表示能监听任何的ip地址的访问,为127.0.0.1表示本机地址,也就是会换地址,这两个试验过。可行,以实现局域网内的tcp、udpc传输方式。
address.sin_port=htons(9734);端口号记得此端口号客户端与服务端一定是绑定到同一个ip的端口号上。
第三步:bind在connect()或listen()调用前使用,int bind( int sockfd , const struct sockaddr * my_addr, socklen_t addrlen);
第一参数:一般为套接字创建成功后的返回值
第二参数:sockaddr:标识一未捆绑套接口的描述字。要是类型不一样用强制转换即可
第三参数:为sockaddr结构体所占长度
第四步:调用listen函数,函数原型int listen( int s, int backlog);
S:用于标识一个已捆绑未连接套接口的描述字。及创建套接字返回成功后的返回值
backlog:等待连接队列的最大长度。
第五步:accept函数原型int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
客户端:
客户端与服务端不同的是客户端只需要创建套接字---------写入与服务端一样的sockaddr_in几个总要成员参数值-------调用connect函数--------,之后再操作
recv与send函数即可
connect()函数:原型: int connect(int s, const struct sockaddr * name, int namelen);
第一参数:一般为socket函数的返回值
第二参数:name:指向要连接套接字的sockaddr结构体的指针
第三参数为 结构体长度用sizeof求得
代码如下:
服务端:
<pre name="code" class="cpp">#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int i,byte;
char char_send,char_recv;
server_sockfd = socket(AF_INET,SOCK_STREAM,0);//创建
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("0.0.0.0");//可换成回环地址实验
server_address.sin_port=htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_len); //捆绑套套接字
listen(server_sockfd,5); //监听
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, //是否接受连接
(struct sockaddr *)&client_address,(socklen_t *)&(client_len));
printf("server wait kehu quest connect2\n");
for(i=0,char_send = '1';i<5;i++,char_send++)
{
if((byte=recv(client_sockfd,&char_recv,1,0))==-1)//此处需注意接收函数的参数
{
perror("recv");
exit(EXIT_FAILURE);
}
printf("receive from client is %c\n",char_recv);
if((byte=send(client_sockfd,&char_send,1,0))==-1)
{
perror("send");
exit(EXIT_FAILURE);
}
}
shutdown(client_sockfd,2); //关闭连接函数
shutdown(server_sockfd,2);
}
客户端:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int sockfd;
int len;
struct sockaddr_in address;
int result;
int i,byte;
char char_send,char_recv;
printf("server wait kehu quest connect1\n");
sockfd = socket(AF_INET,SOCK_STREAM,0); //创建套接字,至于参数查相应手册即可
if(sockfd<0)//判断套接字创建是否成功,
{ //这条语句按语法来说其实可以更上一条语句
//连着写在一起但是不成功后来我改成这样就行了,不知道为什么,可能是系统原因等
printf("socket failure\n");
exit(0);
}
printf("server wait kehu quest connect3\n");
address.sin_family = AF_INET; //标识ipv4地址
address.sin_addr.s_addr = inet_addr("192.168.1.104");//可换成回环地址
address.sin_port=htons(9734); //端口号
len = sizeof(address);
result = connect(sockfd,(struct sockaddr *)&address,len);
if(result<0)
{
printf("connect to failure\n");
exit(EXIT_FAILURE);//提示代码是否执行函数
}
for(i=0,char_send = 'A';i<5;i++,char_send++)
{
if((byte=send(sockfd,&char_send,1,0))==-1)
{
perror("send");
exit(EXIT_FAILURE);
}
if((byte=recv(sockfd,&char_recv,1,0))==-1)
{
perror("recv");
exit(EXIT_FAILURE);
}
printf("receive from server %c\n",char_recv);
}
close(sockfd);//套接字关闭函数
exit(0);
}
之后又实验了udp,upd没有tcp服务端的listen,accept,即没有监听与等待连接,有bind函数相当于是时时克克都已经在接受状态,还有接受发送函数为recvfrom与sendto两个函数,具体阐述查看手册,udp的两端程序差别不大,感觉都差不多,就难得写了。。。。。。。。。。。。