Linux socket通讯编程
上一篇 / 下一篇 2013-05-13 13:36:01 / 个人分类:测试基础
一个android的驱动层测试让我初步接触了下Linux socket通讯编程相关的基础知识。项目的client端软件与server端通过usb串口通信,项目需要修改为client与server端通过网口来通信。所以需要编写一个UDP通讯的client端去测试通讯是否正常以及server端相应数据是否正确。
客户端通过socket通讯的大概流程是:建立socket、绑定bind、放送数据sendto、接收数据recvfrom、关闭通讯close。考虑到发送和接收如果有先后通讯顺序,会导致有数据延迟,或者容易buff满,所以发送和接收需要有两个独立的线程来处理。大致如下:
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#define PORT_SERV 8888
#define BUFF_LEN 256
unsigned char dectivate_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x00};
unsigned char init_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x01};
unsigned char set_resolution_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x02,0x00,0x00,0x00,0x00};
unsigned char set_config_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x03,0x00,0x00,0x00,0x00};
unsigned char start_scan_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x04};
unsigned char set_freq_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char set_touchsize_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x09,0x00,0x00,0x00,0x00};
unsigned char set_activeled_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x1D,0x00,0x00,0x00,0x00};
unsigned char single_scan_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x03,0x0F,0x00,0x00};
unsigned char product_id_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x29};
unsigned char status_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x1E};
unsigned char suspend_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x0A};
unsigned char resume_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x06};
unsigned char validate_connect_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0xEF};
unsigned char invalid_notify__buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x02,0xFE,0x00};
int running = 1;
struct pthread_rec{
int s;
struct sockaddr_in *addr_serv;
unsigned char read_buf[BUFF_LEN];
};
static int getch(void)
{
struct termios oldt,newt;
int ch;
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "this problem should be run at a terminal\n");
exit(1);
}
// save terminal setting
if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
perror("save the terminal setting");
exit(1);
}
// set terminal as need
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
perror("set terminal");
exit(1);
}
ch = getchar();
// restore termial setting
if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
perror("restore the termial setting");
exit(1);
}
return ch;
}
static void udpclie_echo(int s, struct sockaddr *to, unsigned char *buff)
{
int n, i=0;
unsigned char read_buff[BUFF_LEN];
struct sockaddr_in from;
int len = sizeof(*to);
n = sendto(s, buff, BUFF_LEN, 0, to, len);
if(n == -1)
{
printf("sendto error\n");
return ;
}
printf("send successfully\n");
}
static void udpclie_rec(struct pthread_rec *t)
{
int n,i=0;
int len = sizeof(*(t->addr_serv));
struct sockaddr_in from;
// printf("s is %d",t->s);
while(running)
{
// printf("running %d",running);
n = recvfrom(t->s, t->read_buf, BUFF_LEN, 0, (struct sockaddr *)&from, &len);
// printf("n is %d", n);
if(n == -1)
{
printf("recvfrom error\n");
return ;
}
for(i=0; i<32;i++)
{
if(!(i%8))
printf("\n");
printf("0x%x, ",t->read_buf[i]);
}
printf("\n");
printf("continue to select num:\n");
}
}
int main(int argc, char *argv[])
{
int s;
int key = 0;
struct sockaddr_in addr_serv, addr_clie;
//*******************************************************
struct pthread_rec a;
char str[16];
int n;
int ret_rec = -1;
pthread_t pt_rec;
printf("请输入服务器IP:\n");
scanf("%s",str);
printf("请输入服务器端口号(8888)\n");
scanf("%d",&n);
//*************************************************
s = socket(AF_INET, SOCK_DGRAM, 0);
// printf("s_send is %d",s);
if(s < 0)
{
printf("socket err\n");
return -1;
}
//******************************************
struct ifreq ifr;
strcpy(ifr.ifr_name,"eth0");
if(ioctl(s, SIOCGIFADDR, &ifr) < 0)
perror("ioctl");
printf("客户端IP:%s\n",inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr));
//*******************************************
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = inet_addr(str);
addr_serv.sin_port = htons(n);
bind(s, (struct sockaddr*)&addr_serv, sizeof(addr_serv));
a.s = s;
a.addr_serv = &addr_serv;
ret_rec=pthread_create(&pt_rec, NULL, (void*)udpclie_rec, &a);
if(ret_rec != 0)
{
printf("can not creat thread for receiving data\n");
return -1;
}
printf("select number:\n");
while(1)
{
//set_buzzer_freq(freq);
//printf( "\tFreq = %d\n", freq );
//printf("select number:\n");
key = getch();
if(key != 10)
{
printf("you input is ");
printf("%c\n",key);
}
switch(key) {
case '0':
udpclie_echo(s, (struct sockaddr *)&addr_serv, dectivate_buf);
break;
case '1':
udpclie_echo(s, (struct sockaddr *)&addr_serv, init_buf);
break;
case '2':
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_resolution_buf);
break;
case '3':
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_config_buf);
break;
case '4': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, start_scan_buf);
break;
case '5': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_freq_buf);
break;
case '6': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_touchsize_buf);
break;
case '7': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_activeled_buf);
break;
case '8': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, single_scan_buf);
break;
case '9': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, product_id_buf);
break;
case 'a': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, status_buf);
break;
case 'b':
udpclie_echo(s, (struct sockaddr *)&addr_serv, suspend_buf);
break;
case 'c':
udpclie_echo(s, (struct sockaddr *)&addr_serv, resume_buf);
break;
case 'd':
udpclie_echo(s, (struct sockaddr *)&addr_serv, validate_connect_buf);
break;
case 'e':
udpclie_echo(s, (struct sockaddr *)&addr_serv, invalid_notify__buf);
break;
case 'z':
case EOF:
//stop_buzzer();
exit(0);
default:
break;
}
}
//udpclie_echo(s, (struct sockaddr *)&addr_serv);
close(s);
return 0;
}
客户端通过socket通讯的大概流程是:建立socket、绑定bind、放送数据sendto、接收数据recvfrom、关闭通讯close。考虑到发送和接收如果有先后通讯顺序,会导致有数据延迟,或者容易buff满,所以发送和接收需要有两个独立的线程来处理。大致如下:
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#define PORT_SERV 8888
#define BUFF_LEN 256
unsigned char dectivate_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x00};
unsigned char init_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x01};
unsigned char set_resolution_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x02,0x00,0x00,0x00,0x00};
unsigned char set_config_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x03,0x00,0x00,0x00,0x00};
unsigned char start_scan_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x04};
unsigned char set_freq_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char set_touchsize_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x09,0x00,0x00,0x00,0x00};
unsigned char set_activeled_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x05,0x1D,0x00,0x00,0x00,0x00};
unsigned char single_scan_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x03,0x0F,0x00,0x00};
unsigned char product_id_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x29};
unsigned char status_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x1E};
unsigned char suspend_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x0A};
unsigned char resume_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x06};
unsigned char validate_connect_buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0xEF};
unsigned char invalid_notify__buf[BUFF_LEN]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x02,0xFE,0x00};
int running = 1;
struct pthread_rec{
int s;
struct sockaddr_in *addr_serv;
unsigned char read_buf[BUFF_LEN];
};
static int getch(void)
{
struct termios oldt,newt;
int ch;
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "this problem should be run at a terminal\n");
exit(1);
}
// save terminal setting
if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
perror("save the terminal setting");
exit(1);
}
// set terminal as need
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
perror("set terminal");
exit(1);
}
ch = getchar();
// restore termial setting
if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
perror("restore the termial setting");
exit(1);
}
return ch;
}
static void udpclie_echo(int s, struct sockaddr *to, unsigned char *buff)
{
int n, i=0;
unsigned char read_buff[BUFF_LEN];
struct sockaddr_in from;
int len = sizeof(*to);
n = sendto(s, buff, BUFF_LEN, 0, to, len);
if(n == -1)
{
printf("sendto error\n");
return ;
}
printf("send successfully\n");
}
static void udpclie_rec(struct pthread_rec *t)
{
int n,i=0;
int len = sizeof(*(t->addr_serv));
struct sockaddr_in from;
// printf("s is %d",t->s);
while(running)
{
// printf("running %d",running);
n = recvfrom(t->s, t->read_buf, BUFF_LEN, 0, (struct sockaddr *)&from, &len);
// printf("n is %d", n);
if(n == -1)
{
printf("recvfrom error\n");
return ;
}
for(i=0; i<32;i++)
{
if(!(i%8))
printf("\n");
printf("0x%x, ",t->read_buf[i]);
}
printf("\n");
printf("continue to select num:\n");
}
}
int main(int argc, char *argv[])
{
int s;
int key = 0;
struct sockaddr_in addr_serv, addr_clie;
//*******************************************************
struct pthread_rec a;
char str[16];
int n;
int ret_rec = -1;
pthread_t pt_rec;
printf("请输入服务器IP:\n");
scanf("%s",str);
printf("请输入服务器端口号(8888)\n");
scanf("%d",&n);
//*************************************************
s = socket(AF_INET, SOCK_DGRAM, 0);
// printf("s_send is %d",s);
if(s < 0)
{
printf("socket err\n");
return -1;
}
//******************************************
struct ifreq ifr;
strcpy(ifr.ifr_name,"eth0");
if(ioctl(s, SIOCGIFADDR, &ifr) < 0)
perror("ioctl");
printf("客户端IP:%s\n",inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr));
//*******************************************
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = inet_addr(str);
addr_serv.sin_port = htons(n);
bind(s, (struct sockaddr*)&addr_serv, sizeof(addr_serv));
a.s = s;
a.addr_serv = &addr_serv;
ret_rec=pthread_create(&pt_rec, NULL, (void*)udpclie_rec, &a);
if(ret_rec != 0)
{
printf("can not creat thread for receiving data\n");
return -1;
}
printf("select number:\n");
while(1)
{
//set_buzzer_freq(freq);
//printf( "\tFreq = %d\n", freq );
//printf("select number:\n");
key = getch();
if(key != 10)
{
printf("you input is ");
printf("%c\n",key);
}
switch(key) {
case '0':
udpclie_echo(s, (struct sockaddr *)&addr_serv, dectivate_buf);
break;
case '1':
udpclie_echo(s, (struct sockaddr *)&addr_serv, init_buf);
break;
case '2':
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_resolution_buf);
break;
case '3':
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_config_buf);
break;
case '4': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, start_scan_buf);
break;
case '5': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_freq_buf);
break;
case '6': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_touchsize_buf);
break;
case '7': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, set_activeled_buf);
break;
case '8': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, single_scan_buf);
break;
case '9': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, product_id_buf);
break;
case 'a': //single scanning
udpclie_echo(s, (struct sockaddr *)&addr_serv, status_buf);
break;
case 'b':
udpclie_echo(s, (struct sockaddr *)&addr_serv, suspend_buf);
break;
case 'c':
udpclie_echo(s, (struct sockaddr *)&addr_serv, resume_buf);
break;
case 'd':
udpclie_echo(s, (struct sockaddr *)&addr_serv, validate_connect_buf);
break;
case 'e':
udpclie_echo(s, (struct sockaddr *)&addr_serv, invalid_notify__buf);
break;
case 'z':
case EOF:
//stop_buzzer();
exit(0);
default:
break;
}
}
//udpclie_echo(s, (struct sockaddr *)&addr_serv);
close(s);
return 0;
}
TAG:
标题搜索
日历
|
|||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
1 | 2 | 3 | 4 | 5 | 6 | ||||
7 | 8 | 9 | 10 | 11 | 12 | 13 | |||
14 | 15 | 16 | 17 | 18 | 19 | 20 | |||
21 | 22 | 23 | 24 | 25 | 26 | 27 | |||
28 | 29 | 30 |
我的存档
数据统计
- 访问量: 43400
- 日志数: 35
- 建立时间: 2013-03-14
- 更新时间: 2015-11-05