您的位置:首页 > 运维架构 > Linux

Linux下无连接的套接字通信C实现

2014-01-02 19:17 274 查看
不得不说。。。自己懒的程度连自己都受不了。。。虽然一直在学~但处于学完又忘的状态。。。总觉得自己记完笔记又会忘掉。。。555。。。
自己正在慢慢挖掘linux下编程的兴趣,感觉处于混沌状态,都说编程这种东西都得有兴趣才可以编出来的~~希望我对它的兴趣会一直上升~~~
好好记录笔记。。。
无连接的套接字通信即UDP通信~C的实现看起来和java的代码实现差不少额。。。但总的来说,步骤都差不多。。。flashplayer版本太低了,找天补"21天linux'的图~
补上:



具体说法:
服务器:1.创建socket; 2.socket绑定端口; 3.读取接收到的信息; 4.发送消息
socket() bind() recvfrom() sendto()
客户端:1.创建socket; 2.连接一个指定的计算机和端口; 3.发送消息; 4.读取接收到的信息
socket() bind() sendto() recvfrom()

服务器源码:
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#define LOCALPORT 4567

int main(int argc, char *argv[])
{
int mysock, len;
struct sockaddr_in addr;
int i = 0;
char msg[256];
int addr_len;
if((mysock=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("error");
exit(1);
}
else
{
printf("socket created.\n");
printf("socket id: %d\n",mysock);
}
addr_len = sizeof(struct sockaddr_in);
bzero(&addr, sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(LOCALPORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY);//0.0.0.0任意地址
if(bind(mysock, &addr, sizeof(addr)) < 0)
{
perror("connect");
exit(1);
}
else
{
printf("bind ok.\n");
printf("local port : %d\n",LOCALPORT);
}
while(1)
{
bzero(msg,sizeof(msg));
/*接收到的信息*/
len=recvfrom(mysock,msg,sizeof(msg),0,&addr,&addr_len);
printf("%d :",i);
i++;
printf("msg from: %s\n",inet_ntoa(addr.sin_addr));
printf(" msg len: %d\n",len);
printf(" msg: %s\n",msg);
sendto(mysock,msg,len,0,&addr,addr_len);
/*以上将字符串返回给客户端*/
}
return 0;
}

知识点补充:
套接字=传输层协议+端口号+IP地址
套接字相关类型:sockaddr或sockaddr_in
struct sockaddr//系统中定义好的
{
unsigned short int sa_family;
char sa_data[14];
};
sa_family:指定通信的地址类型。如果是TCP/IP通信,则为AF_INET
sa_data:最多14个字符长度,用来保存IP地址和端口信息
struct socketaddr_in
{
unsigned short int sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
struct in addr
{
uint32_t s_addr;//保存一个IP地址
};
sin_family和sa_family相同
sin_port:套接字使用的端口号
sin_addr:需要访问的IP地址
sin_zero:未使用的字段,填充为0

好的~接下来开始看代码(至于什么时候导入什么包需要另开blog记下来才可以!)
socket(AF_INET, SOCK_DGRAM, 0)创建socket并将返回号码到mysock,创建成功后,注意套接字放到addr中,bzero(&addr,sizeof(addr))-->bzero(void *s, int n)功能:置字节字符串s的前n个字节为零且包括‘\0’。建议改成memset()函数作初始化。初始化addr的各项参数,参考struct socketaddr_in;通过bind(mysock,&addr,sizeof(addr))绑定端口;然后就可以等待客户端给服务器端发送消息了~~
while循环一直等待客户端发送消息,recvfrom(mysock,msg,sizeof(msg),0,&addr,&addr_len)负责接收消息,接收的长度放到len中。inet_ntoa(addr.sin_addr)将一个IP转换成一个互联网标准点分格式的字符串,sendto(mysock,msg,len,0,&addr,addr_len)将字符串返回给客户端。

接下来是客户端的代码:
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#define REMOTEPORT 4567
#define REMOTEIP "127.0.0.1"
int main(int argc, char *argv[])
{
int s,len;
struct sockaddr_in addr;//套接字结构体
int addr_len;
char msg[256];
int i = 0;
if((s=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("error");
exit(1);
}
else
{
printf("socket created.\n");
printf("socket id:%d\n",s);
printf("remote ip:%s\n",REMOTEIP);
printf("remote port:%d\n",REMOTEPORT);
}
addr_len=sizeof(struct sockaddr_in);
bzero(&addr, sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(REMOTEPORT);
addr.sin_addr.s_addr=inet_addr(REMOTEIP);//struct in_addr sin_addr
while(1)
{
bzero(msg,sizeof(msg));
len = read(STDIN_FILENO, msg, sizeof(msg));
/*s是建立好的socket,msg是发送的字符串,len是字符长度,flag=0*/
sendto(s,msg,len,0,&addr,addr_len);
printf("\nInput message: %s\n",msg);
/*这是接受到的信息*/
len = recvfrom(s,msg,sizeof(msg),0,&addr,&addr_len);
printf("%d: ",i);
i++;
printf("Received message: %s\n",msg);/*这是服务器返回的信息*/
}
return 0;
}
解释一下和上面有差异和没解析的部分~
htonl:将计算机中的32位长整型数转换成网络字符顺序的32位长整型数
htons:(同上,16位)
ntohl:将网络字符顺序的32位长整型数转换成计算机中的32位长整型数
ntohs:(同上,16位)
read(STDIN_FILENO, msg,sizeof(msg));函数等待用户键盘输入
本文出自 “再累也要开心D” 博客,请务必保留此出处http://zhangzhang.blog.51cto.com/6250085/1347811
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: