网络编程:
1、概念:客户端:接收数据的一端
服务器:提供数据的一端
2、网络通讯协议的选择:
Tcp:面向链接可靠的流式服务,当双发持续的发送数据采用面向连接方式
内核维护一条专用传输线路用来通信
Udp:无连接 不可靠的数据报服务
可不可靠看两点:能不能收到数据,数据能不能到
3、编程
Tcp的编程流程
Server:socket bind listen (监听有没有链接)、accept recv/sent close
Client:socket bind(可有可无,服务器可自动获取客户端地址) connect recv/send close
函数详解:以下函数成功均返回0,失败返回-1
创建套接字:
int sockfd=socket(int domain,int type,int prototal)
第一个参数:协议族,通常使用AF_INET与PF_INET
第二个参数: 选择什么协议SOCK_STREAM(tcp)与SOCK_DGRAM(udp)
套接字绑定ip和端口号
Socket命名:
Int bind(int sockfd,conts struct sockaddr *addr,socklen_t addrlen)
第一个参数套接字id,第二个参数保存ip和端口号的结构体(里面有地址族类型)现在用sockaddr_in
注:在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。
命名失败原因:端口号被占用,ip地址错误
监听套接字:
Int listen(int sockfd,int backlog);
创建一个监听队列,第二个参数表示创建队列的大小
接受连接:
int c=accept(int sockfd,(struct sockaddr*)&cli,&len);这个返回值是文件描述符,指向建立的那条链接
Socket文件描述符只负责链接,而此时的c才是传送数据的
发起连接:
Int connect(int sockfd,struct sockaddr* addr,int* addrlen);
第一个参数是系统为客户端自动分配的socket,第二个参数为服务器监听的socket的地址
读取数据:
ssise_t recv(int sockfd , void *buf , size_t len , int flags)
recv读取sockfd上的数据,buf和len代表数据的地址和大小,第四个参数通常啊设为0
发送数据:
ssise_t send (int sockfd , void *buf , size_t len , int flags)
send往sockfd上写数据,buf和len代表数据的地址和大小,第四个参数通常设为0
代码示例:
客户端:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
void main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);//5000一下谨生使用 1024是电脑自身使用
ser.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
assert(res!=-1);
listen(sockfd,5);
while(1)
{
int len=sizeof(cli);
int c=accept(sockfd,(struct sockaddr*)&cli,&len);
assert(c!=-1);
char buff[128]={0};
recv(c,buff,127,0);
printf("recv:%s\n",buff);
send(c,"ok",strlen("ok"),0);
if(strncmp(buff,"end",3)==0)
{
break;
}
send(c,"ok",strlen("ok"),0);
if(strncmp(buff,"end",3)==0)
{
break;
}
close(c);
}
close(sockfd);
}
客户端:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
void main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);//5000一下谨生使用 1024是电脑自身使用
ser.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
assert(res!=-1);
while(1)
{
printf("please input\n");
char buff[128]={0};
fgets(buff,127,stdin);
send(sockfd,buff,strlen(buff),0);
recv(sockfd,buff,127,0);
printf("recv:%s\n",buff);
}
close(sockfd);
}