@Dubyoo
2014-06-13T19:28:36.000000Z
字数 4294
阅读 3243
服务端:socket ---> bind ---> recvfrom ---> sendto ---> close
客户端:socket -------------> sendto ---> recvfrom ---> close
/* socket:生成一个套接口描述符 */
int socket(int domain, int type, int protocol);
//domain ---> AF_INET: IPv4; AF_INET6: IPv6;
//type ---> SOCK_STREAM: tcp; SOCK_DGRAM: udp;
//protocol ---> 指定socket传输所用的协议编号,通常为0 。
/* bind:绑定一个端口号和ip地址,使套接口与端口号和ip地址相关联 */
int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
// sockfd为前面socket的返回值。
// my_addr为结构体指针变量,结构体如下
// addrlen:sockaddr的结构体长度。通常是sizeof(struct sockaddr);
struct sockaddr //此结构体不常用
{
unsigned short int sa_family; //调用socket()时的domain参数,即AF_INET值。
char sa_data[14]; //最多使用14个字符长度
};
//使用ipv4时,其socketaddr结构定义便为
struct sockaddr_in //常用的结构体
{
unsigned short int sin_family; //即为sa_family AF_INET
uint16_t sin_port; //为使用的port编号
struct in_addr sin_addr; //为IP 地址
unsigned char sin_zero[8]; //未使用
};
struct in_addr
{
uint32_t s_addr;
};
/*bind实例*/
struct sockaddr_in my_addr; //定义结构体变量
memset(&my_addr, 0, sizeof(struct sockaddr)); //将结构体清空
//或bzero(&my_addr, sizeof(struct sockaddr));
my_addr.sin_family = AF_INET; //表示采用Ipv4网络协议
my_addr.sin_port = htons(8888);
//表示端口号为8888,通常是大于1024的一个值。
//htons()用来将参数指定的16位hostshort转换成网络字符顺序
my_addr.sin_addr.s_addr = inet_addr("192.168.1.13");
// inet_addr()用来将IP地址字符串转换成网络所使用的二进制数字,如果为INADDR_ANY,这表示服务器自动填充本机IP地址。
int iret = bind(sfd, (struct sockaddr*)&my_str, sizeof(struct socketaddr));
if(iret == -1)
{
perror("bind");
close(sfd);
exit(-1);
}
注:
my_addr.sin_port 置为 0,函数会自动为你选择一个未占用的端口来使用。
my_addr.sin_addr.s_addr 置为 INADDR_ANY,系统会自动填入本机IP地址。
/* 从任意IP接收消息存入缓冲区,并将客户机IP放入内存 */
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
//sockfd: socket描述符
//buf: 接收的字符串存入缓冲区buf中
//len: 缓冲区长度
//flags: 通常为0
//from是一个struct sockaddr类型的变量,该变量保存连接机的IP地址及端口号。
//fromlen常置为sizeof (struct sockaddr)。
//当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。
/* 发送消息到指定IP */
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
//sockfd: socket描述符
//msg: 一般为常量字符串,发出的消息
//len: msg长度
//flags: 通常为0
//to表示目地机的IP地址和端口号信息
//tolen常常被赋值为sizeof (struct sockaddr)
close(sock_fd) ;
/*server.c*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main(int argc, char * argv[]) // ---> ./server.exe [port]
{
int server_fd, iret ;
char recv_buf[128], send_buf[128] ;
struct sockaddr_in server_addr, client_addr ;
// 1.socket
server_fd = socket(AF_INET, SOCK_DGRAM, 0) ;
if(server_fd == -1)
{
perror("socket");
exit(-1) ;
}
// 2.bind
memset(&server_addr, 0, sizeof(server_addr)) ;
server_addr.sin_family = AF_INET ;
server_addr.sin_port = htons(atoi(argv[1])) ;
server_addr.sin_addr.s_addr = INADDR_ANY ;
iret = bind(server_fd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) ;
if(iret == -1)
{
perror("bind") ;
exit(-1) ;
}
// 3.recvfrom
memset(&client_addr, 0, sizeof(client_addr)) ;
memset(recv_buf, 0, 128) ;
int len = sizeof(client_addr) ;
recvfrom(server_fd, recv_buf, 128, 0, (struct sockaddr*)&client_addr, &len) ;
char ip[32] = "" ;
printf("receive from ip : %s, port : %d, message : %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), recv_buf) ;
// 4.sendto
memset(send_buf, 0, sizeof(client_addr)) ;
strcpy(send_buf, "received !\n") ;
sendto(server_fd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&client_addr, sizeof(client_addr)) ;
// 5.close
close(server_fd) ;
return 0;
}
/*client.c*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main(int argc, char * argv[]) // ---> ./exe [ip] [port]
{
int client_fd, iret ;
char recv_buf[128], send_buf[128] ;
struct sockaddr_in server_addr, client_addr ;
// 1.socket
client_fd = socket(AF_INET, SOCK_DGRAM, 0) ;
if(client_fd == -1)
{
perror("socket") ;
exit(-1) ;
}
memset(&server_addr, 0, sizeof(server_addr)) ;
server_addr.sin_family = AF_INET ;
server_addr.sin_port = htons(atoi(argv[2])) ;
server_addr.sin_addr.s_addr = inet_addr(argv[1]) ;
// 2.sendto
memset(send_buf, 0, 128) ;
strcpy(send_buf, "Hello guys !\n") ;
sendto(client_fd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) ;
// 3.recvfrom
memset(&server_addr, 0, sizeof(server_addr)) ;
memset(recv_buf, 0, 128) ;
int len = sizeof(server_addr) ;
recvfrom(client_fd, recv_buf, 128, 0, (struct sockaddr*)&server_addr, &len) ;
char ip[32] = "" ;
printf("received form ip :%s, port : %d, message : %s\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port), recv_buf) ;
// 4.close
close(client_fd) ;
return 0 ;
}