网络编程——Socket(Linux套接字编程) 讲述了TCP协议下的Socket传输规则。另外一种则是UDP下的传输,如下:
在网络传输协议中,TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接。TCP有一种“重传确认”机制,即接收端收到数据后要发出一个肯定确认的信号,发送端如果收到接收端肯定确认的信号,就会继续发送其他的数据,如果没有,它就会重新发送。
相对而言,UDP协议则是一种无连接的,不可靠的数据报(SOCK_DGRAM)传输服务。使用UDP套接口不用建立连接,服务端在调用socket()生成一个套接字并调用bind()绑定端口后就可以进行通信(recvfrom函数和sendto函数)了;客户端在用socket()生成一个套接字后就可以向服务端地址发送和接收数据了。
此处需要特别注意:TCP使用的是流套接字(SOCK_STREAM),UDP使用的是数据报套接字(SOCK_DGRAM)
–
SOCK_STREAM:
提供可靠的面向连接传输的数据流,保证数据在传输过程中无丢失、无损坏和无冗余。
INET
地址簇中的
TCP
协议支持该套接字。
–
SOCK_DGRAM:
提供数据的双向传输,但不保证消息地准确到达,即使消息能够到达,也无法保证其顺序性,并可能有冗余或损坏。
INET
地址簇中的
UDP
协议支持该套接字。
服务器端:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
int main()
{
int udpserver=-1; //定义UDP套接口描述字
int clientlen= 0;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
char data[80]="The Client's arguement is:";
char temp[80];
//创建UDP套接字
udpserver = socket (AF_INET,SOCK_DGRAM,0);
if(udpserver == -1)
{
perror(" creating sockrt failed! \n");
exit(1);
}
//设置服务器连接地址和端口,对于IPv4
server_addr.sin_family = AF_INET; //TCP地址结构
server_addr.sin_port = htons(9736); //绑定到9736端口,并将端口转换成网络数据类型
server_addr.sin_addr.s_addr = htonl (INADDR_ANY);//不指定IP地址
//指定IP地址为127.0.0.1;inet_addr将点分十进制转换成32位数字网络字节顺序
//server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//bind绑定套接字。成功返回0,失败返回-1
bind(udpserver, (struct sockaddr*)&server_addr, sizeof(server_addr));
//忽略子进程停止或退出信号
signal(SIGCHLD, SIG_IGN);
//等待客户连接请求
while(1)
{
//存储客户端端口数据
clientlen=sizeof(client_addr);
//最好利用recvfrom()返回值判断下接收数据是否成功
recvfrom(udpserver,temp,80,0,(struct sockaddr*)&client_addr,&clientlen);
if(fork()==0 ) //子进程返回成功
{
printf("The recv data is:%s",temp);
//处理接收的数据
strcat(data,temp);
sendto(udpserver,data,sizeof(data),0,(struct sockaddr*)&client_addr,clientlen);
exit(0);
}
}
close(udpserver);
return 0;
}
客户端:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc , char *argv[])
{
int udpscoket=-1;
struct sockaddr_in address;
int dest_len=0;
char temp[80];
if(argc<=1)
{
perror("Please input the arguement after executable file's name!\n");
exit(0);
}
printf("\nClient input's argument is:%s\n",argv[1]);
//创建UDP套接字
udpscoket = socket(AF_INET,SOCK_DGRAM,0);
//设置服务器连接信息
address.sin_family = AF_INET; //TCP地址结构
address.sin_port = htons(9736); //绑定到9736端口,并将端口转换成网络数据类型
address.sin_addr.s_addr = inet_addr("127.0.0.1");
dest_len=sizeof(address);
//发送数据到服务器
sendto(udpscoket, argv[1],80,0,(struct sockaddr*)&address,dest_len);
//接收服务器信息
recvfrom(udpscoket, temp,80, 0, 0, 0);
printf("\n%s\n",temp);
close(udpscoket);
exit(0);
}
测试结果: