C:如何通过套接字读取和解压缩消息?
我正在尝试通过套接字接收更新的消息并解压缩 数据。我想使用update_client函数来更新服务器的 客户的内部代表协调并响应 具有所需值的客户端 我想我应该使用recv将完整消息(长度为UPDATE\u CMD\u LEN)读入缓冲区 然后按以下格式解包包含消息的数据:C:如何通过套接字读取和解压缩消息?,c,sockets,buffer,unpack,C,Sockets,Buffer,Unpack,我正在尝试通过套接字接收更新的消息并解压缩 数据。我想使用update_client函数来更新服务器的 客户的内部代表协调并响应 具有所需值的客户端 我想我应该使用recv将完整消息(长度为UPDATE\u CMD\u LEN)读入缓冲区 然后按以下格式解包包含消息的数据: U<id><fields of gpscoords> 客户c #include <stdio.h> #include <string.h> #include &l
U<id><fields of gpscoords>
客户c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "gps.h"
#define CMD_LEN 10
#define LINE_LEN NAME_LEN + 15
#define FIREFOX "/usr/bin/firefox"
void make_route_url(char *url, gpscoords *pos, gpscoords *target) {
char pos_sign_n;
char pos_sign_e;
char tar_sign_n;
char tar_sign_e;
pos_sign_n = pos->north ? '+' : '-';
pos_sign_e = pos->east ? '+' : '-';
tar_sign_n = target->north ? '+' : '-';
tar_sign_e = target->east ? '+' : '-';
sprintf(url,
"http://map.project-osrm.org/?z=13&loc=%c%u.%u,%c%u.%u&loc=%c%u.%u,%c%u.%u",
pos_sign_n, pos->lat, pos->lat_frac,
pos_sign_e, pos->lon, pos->lon_frac,
tar_sign_n, target->lat, target->lat_frac,
tar_sign_e, target->lon, target->lon_frac);
}
void show_route(gpscoords *pos, gpscoords *target) {
// char url[75];
fprintf(stderr, "show_route not implemented!\n");
exit(-1);
}
int run_client(char *name, char *serverip) {
char *cmdline;
size_t line_len;
char cmd[11];
gpsinfo info;
gpscoords pos, targetpos;
char targetname[NAME_LEN];
bzero(targetname, NAME_LEN);
bzero(&info, sizeof(info));
bzero(&pos, sizeof(pos));
bzero(&targetpos, sizeof(targetpos));
if (register_client(serverip, name, &info) == -1) {
perror("Error registering client.");
return -1;
}
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to send initial position to server.\n");
exit(-1);
}
for (;;) {
printf("Command: ");
line_len = 0;
cmdline = NULL;
getline(&cmdline, &line_len, stdin);
if (strncmp(cmdline, "update", 3) == 0) {
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to update.\n");
}
} else if (strncmp(cmdline, "find", 3) == 0) {
sscanf(cmdline, "%10s %25s", cmd, targetname);
if (get_position(&info, targetname, &targetpos) == -1) {
printf("Couldn't find target.\n");
} else {
show_route(&pos, &targetpos);
}
} else if (strncmp(cmdline, "quit", 4) == 0) {
free(cmdline);
break;
}
free(cmdline);
}
if (unregister_client(&info) == -1) {
perror("Error unregistering client.");
return -1;
}
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: ./client <client name> <server_ip>\n");
return 0;
}
return run_client(argv[1], argv[2]);
}
#包括
#包括
#包括
#包括
#包括“gps.h”
#定义CMD_LEN 10
#定义行名称\u LEN+15
#定义FIREFOX“/usr/bin/FIREFOX”
void make_route_url(char*url,gpscoords*pos,gpscoords*target){
字符位置符号;
字符位置符号;
字符标记;
字符标记;
pos_sign_n=pos->north?'+':'-';
pos_sign_e=pos->east?“+”:“-”;
tar_sign_n=target->north?'+':'-';
tar_sign_e=target->east?'+':'-';
sprintf(url,
"http://map.project-osrm.org/?z=13&loc=%c%u.%u,%c%u.%u&loc=%c%u.%u,%c%u.%u“,
位置符号,位置->横向,位置->横向断裂,
位置符号e,位置->长度,位置->长度分形,
沥青标志,目标->横向,目标->横向压裂,
焦油标志,目标->长,目标->长压裂);
}
无效显示路径(gpscoords*位置,gpscoords*目标){
//charurl[75];
fprintf(标准“显示未执行的路线!\n”);
出口(-1);
}
int run_客户端(字符*名称,字符*服务器IP){
char*cmdline;
尺寸线;
char-cmd[11];
gpsinfo信息;
gpscoords pos、targetpos;
char targetname[名称];
bzero(目标名称、名称);
bzero(&info,sizeof(info));
bzero(&pos,sizeof(pos));
bzero(和targetpos,sizeof(targetpos));
if(register_client(serverip、name和info)=-1){
perror(“注册客户时出错”);
返回-1;
}
查找自身(&pos);
如果(更新位置(&info,&pos)=-1){
printf(“未能将初始位置发送到服务器。\n”);
出口(-1);
}
对于(;;){
printf(“命令:”);
直线长度=0;
cmdline=NULL;
getline(&cmdline,&line_len,stdin);
如果(strncmp(cmdline,“更新”,3)==0){
查找自身(&pos);
如果(更新位置(&info,&pos)=-1){
printf(“更新失败。\n”);
}
}else if(strncmp(cmdline,“find”,3)=0){
sscanf(cmdline,“%10s%25s”,cmd,targetname);
if(获取位置(&info、targetname和targetpos)=-1){
printf(“找不到目标。\n”);
}否则{
显示路线(&pos,&targetpos);
}
}else if(strncmp(cmdline,“退出”,4)=0){
免费(cmdline);
打破
}
免费(cmdline);
}
如果(注销客户端(&info)=-1){
perror(“注销客户端时出错”);
返回-1;
}
返回0;
}
int main(int argc,字符**argv){
如果(argc<2){
printf(“用法:./client\n”);
返回0;
}
返回run_客户端(argv[1],argv[2]);
}
插座c
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "sockets.h"
int create_dg_socket(in_port_t port) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
printf("create_dg_socket cannot create socket!");
return -1;
}
// Bind the socket port
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
printf("create_dg_socket cannot bind socket!");
close(sockfd);
return -1;
}
return sockfd;
}
int open_dg_socket(char *ipaddr, in_port_t port, struct sockaddr_in *addr) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
return -1;
}
// Setup
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = inet_addr(ipaddr);
return sockfd;
}
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
if (sendto(sockfd, message, out_len, 0, (struct sockaddr *)&addr, sizeof(*addr)) == -1) {
printf("dg_sendrecv cannot send data!");
return -1;
}
int ret = recvfrom(sockfd, response, in_len, 0, NULL, NULL);
if (ret == -1) {
printf("dg_sendrecv cannot read data!");
return -1;
}
return ret;
}
/*
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ipaddr);
return dg_sendrecv_addr(sockfd, &addr, message, out_len, response, in_len);
}
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“sockets.h”
int create_dg_插座(in_端口\u t端口){
//创建套接字
int sockfd=套接字(AF_INET,SOCK_DGRAM,0);
如果(sockfd==-1){
printf(“创建套接字无法创建套接字!”);
返回-1;
}
//绑定套接字端口
地址中的结构sockaddr\u;
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
地址SINU port=htons(端口);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))!=0){
printf(“创建_dg_套接字无法绑定套接字!”);
关闭(sockfd);
返回-1;
}
返回sockfd;
}
int open_dg_socket(字符*ipaddr,in_port\t port,结构sockaddr\u in*addr){
//创建套接字
int sockfd=套接字(AF_INET,SOCK_DGRAM,0);
如果(sockfd==-1){
返回-1;
}
//设置
addr->sin_family=AF_INET;
地址->单端口=htons(端口);
addr->sin\u addr.s\u addr=inet\u addr(ipaddr);
返回sockfd;
}
内部dg_sendrecv(内部sockfd,
*地址中的结构sockaddr_,
字符*消息,大小为,
字符*响应,大小(英寸){
if(发送到(sockfd,message,out_len,0,(struct sockaddr*)和addr,sizeof(*addr))=-1){
printf(“dg_sendrecv无法发送数据!”);
返回-1;
}
int ret=recvfrom(sockfd,response,in_len,0,NULL,NULL);
如果(ret==-1){
printf(“dg_sendrecv无法读取数据!”);
返回-1;
}
返回ret;
}
/*
内部dg_sendrecv(内部sockfd,
*地址中的结构sockaddr_,
字符*消息,大小为,
字符*响应,大小(英寸){
地址中的结构sockaddr\u;
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
地址SINU port=htons(端口);
addr.sin\u addr.s\u addr=inet\u addr(ipaddr);
返回dg_sendrecv_addr(sockfd,&addr,message,out_len,response,in_len);
}
*/
服务器.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include "sockets.h"
#include "gps.h"
#include "server.h"
#define NUM_CLIENTS 5
char clients[NUM_CLIENTS][NAME_LEN];
gpscoords coords[NUM_CLIENTS];
void do_register(int sockfd, struct sockaddr_in *clientaddr) {
char msg[REGISTER_CMD_LEN];
char *name;
unsigned char id, i;
if (recv(sockfd, msg, REGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving register command.");
exit(-1);
}
// first byte is server command, rest is name
name = &msg[1];
id = NO_RES;
for (i = 0; i < NUM_CLIENTS; ++i) {
if (clients[i][0] == '\0') {
strncpy(clients[i], name, NAME_LEN);
clients[i][NAME_LEN - 1] = '\0';
bzero(&coords[i], sizeof(coords[i]));
id = i + 1;
break;
}
}
if (sendto(sockfd,
&id, sizeof(id),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error replying to client.");
exit(-1);
}
}
void do_unregister(int sockfd, struct sockaddr_in *clientaddr) {
unsigned char msg[UNREGISTER_CMD_LEN];
unsigned char id;
char res = NO_RES;
if (recv(sockfd, &msg, UNREGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving unregister command.");
exit(-1);
}
id = msg[1] - 1;
if (id < NUM_CLIENTS) {
clients[id][0] = '\0';
res = SUCC_RES;
}
if (sendto(sockfd,
&res, sizeof(res),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error responding to client.");
exit(-1);
}
}
int update_client(unsigned char id, gpscoords *pos) {
id -= 1;
if (id >= NUM_CLIENTS)
return -1;
memcpy(&coords[id], pos, sizeof(coords[id]));
return 0;
}
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
/**
* Receive an update message over the socket and unpack the
* data. Then use the update_client function to update the server's
* internal representation of the client co-ordinates. Then respond to the
* client with the required value.
* Use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
* Unpack data, message of following format:
* U<id><fields of gpscoords>
* Character 'U' (meaning update), followed by ID of the client (unsigned char)
* and then the gpscoord structure in network format.
*
* 1. Unpack ID
* 2. Unpack coordinates with (int update_client(unsigned char id, gpscoords *pos)
* which takes ID and pointer to position struct, returns -1 on error and 0 on success
* Server should then respond to client using sendto function and reply
* NO_RES on error and SUCC_RES on success.
*/
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
static gpscoords *get_client(char *name) {
for (int i = 0; i < NUM_CLIENTS; ++i) {
if (strcmp(name, clients[i]) == 0) {
return &coords[i];
break;
}
}
return NULL;
}
void do_get(int sockfd, struct sockaddr_in *clientaddr) {
char msg[GET_CMD_LEN];
char res[GET_RES_LEN];
char *name;
if (recv(sockfd, msg, GET_CMD_LEN, 0) == -1) {
perror("Error receiving get command.");
exit(-1);
}
name = &msg[1];
name[NAME_LEN - 1] = '\0';
gpscoords *pos = get_client(name);
if (pos == NULL) {
res[0] = NO_RES;
} else {
res[0] = SUCC_RES;
pack_gpscoords(pos, &res[1]);
}
if (sendto(sockfd,
&res, GET_RES_LEN,
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error sending result to client.");
exit(-1);
}
}
int serve(int sockfd) {
char cmd;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
for (;;) {
if (recvfrom(sockfd,
&cmd, sizeof(cmd),
MSG_PEEK,
(struct sockaddr *)&clientaddr, &clientaddrlen) == -1) {
exit(-1);
}
switch (cmd) {
case CMD_REGISTER:
do_register(sockfd, &clientaddr);
break;
case CMD_UNREGISTER:
do_unregister(sockfd, &clientaddr);
break;
case CMD_UPDATE:
do_update(sockfd, &clientaddr);
break;
case CMD_GET:
do_get(sockfd, &clientaddr);
break;
default:
break;
}
}
}
void init_info() {
int i;
for (i = 0; i < NUM_CLIENTS; ++i) {
clients[i][0] = '\0';
}
}
int main(int argc, char **argv) {
int sockfd = create_dg_socket(SERVER_PORT);
if (sockfd == -1) {
fprintf(stderr, "Error creating socket!\n");
return -1;
}
init_info();
printf("Server ready.\n");
serve(sockfd);
// Note: server never terminates, we're relying on the system to clean up
// our open socket file descriptor (and shut it down)
return 0;
}
#包括
#包括
#包括
#包括
#包括“sockets.h”
#包括“gps.h”
#包括“server.h”
#定义NUM_客户端5
char客户机[NUM_clients][NAME_LEN];
gpscoords coords[NUM_CLIENTS];
void do_寄存器(int sockfd,struct sockaddr_in*clientaddr){
char msg[寄存器\命令\长度];
字符*名称;
无符号字符id,i;
if(recv(sockfd,msg,REGISTER_CMD_LEN,0)=-1){
perror(“接收寄存器命令时出错”);
出口(-1);
}
//第一个字节是服务器命令,其余是名称
名称=&msg[1];
id=无;
对于(i=0;i#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include "sockets.h"
#include "gps.h"
#include "server.h"
#define NUM_CLIENTS 5
char clients[NUM_CLIENTS][NAME_LEN];
gpscoords coords[NUM_CLIENTS];
void do_register(int sockfd, struct sockaddr_in *clientaddr) {
char msg[REGISTER_CMD_LEN];
char *name;
unsigned char id, i;
if (recv(sockfd, msg, REGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving register command.");
exit(-1);
}
// first byte is server command, rest is name
name = &msg[1];
id = NO_RES;
for (i = 0; i < NUM_CLIENTS; ++i) {
if (clients[i][0] == '\0') {
strncpy(clients[i], name, NAME_LEN);
clients[i][NAME_LEN - 1] = '\0';
bzero(&coords[i], sizeof(coords[i]));
id = i + 1;
break;
}
}
if (sendto(sockfd,
&id, sizeof(id),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error replying to client.");
exit(-1);
}
}
void do_unregister(int sockfd, struct sockaddr_in *clientaddr) {
unsigned char msg[UNREGISTER_CMD_LEN];
unsigned char id;
char res = NO_RES;
if (recv(sockfd, &msg, UNREGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving unregister command.");
exit(-1);
}
id = msg[1] - 1;
if (id < NUM_CLIENTS) {
clients[id][0] = '\0';
res = SUCC_RES;
}
if (sendto(sockfd,
&res, sizeof(res),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error responding to client.");
exit(-1);
}
}
int update_client(unsigned char id, gpscoords *pos) {
id -= 1;
if (id >= NUM_CLIENTS)
return -1;
memcpy(&coords[id], pos, sizeof(coords[id]));
return 0;
}
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
/**
* Receive an update message over the socket and unpack the
* data. Then use the update_client function to update the server's
* internal representation of the client co-ordinates. Then respond to the
* client with the required value.
* Use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
* Unpack data, message of following format:
* U<id><fields of gpscoords>
* Character 'U' (meaning update), followed by ID of the client (unsigned char)
* and then the gpscoord structure in network format.
*
* 1. Unpack ID
* 2. Unpack coordinates with (int update_client(unsigned char id, gpscoords *pos)
* which takes ID and pointer to position struct, returns -1 on error and 0 on success
* Server should then respond to client using sendto function and reply
* NO_RES on error and SUCC_RES on success.
*/
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
static gpscoords *get_client(char *name) {
for (int i = 0; i < NUM_CLIENTS; ++i) {
if (strcmp(name, clients[i]) == 0) {
return &coords[i];
break;
}
}
return NULL;
}
void do_get(int sockfd, struct sockaddr_in *clientaddr) {
char msg[GET_CMD_LEN];
char res[GET_RES_LEN];
char *name;
if (recv(sockfd, msg, GET_CMD_LEN, 0) == -1) {
perror("Error receiving get command.");
exit(-1);
}
name = &msg[1];
name[NAME_LEN - 1] = '\0';
gpscoords *pos = get_client(name);
if (pos == NULL) {
res[0] = NO_RES;
} else {
res[0] = SUCC_RES;
pack_gpscoords(pos, &res[1]);
}
if (sendto(sockfd,
&res, GET_RES_LEN,
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error sending result to client.");
exit(-1);
}
}
int serve(int sockfd) {
char cmd;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
for (;;) {
if (recvfrom(sockfd,
&cmd, sizeof(cmd),
MSG_PEEK,
(struct sockaddr *)&clientaddr, &clientaddrlen) == -1) {
exit(-1);
}
switch (cmd) {
case CMD_REGISTER:
do_register(sockfd, &clientaddr);
break;
case CMD_UNREGISTER:
do_unregister(sockfd, &clientaddr);
break;
case CMD_UPDATE:
do_update(sockfd, &clientaddr);
break;
case CMD_GET:
do_get(sockfd, &clientaddr);
break;
default:
break;
}
}
}
void init_info() {
int i;
for (i = 0; i < NUM_CLIENTS; ++i) {
clients[i][0] = '\0';
}
}
int main(int argc, char **argv) {
int sockfd = create_dg_socket(SERVER_PORT);
if (sockfd == -1) {
fprintf(stderr, "Error creating socket!\n");
return -1;
}
init_info();
printf("Server ready.\n");
serve(sockfd);
// Note: server never terminates, we're relying on the system to clean up
// our open socket file descriptor (and shut it down)
return 0;
}
char buffer[5+sizeof(gpscoords)];
int *int_pointer;
gpscoords *gps_pointer;
int id=1;
gpscoords gps="some gps contend";
int id_frombuffer;
gpscoords gps_frombuffer;
char c_frombuffer;
buffer[0]='U';
int_pointer=(int*)&buffer;
int_pointer+=1;
*int_pointer=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=5;
*gpspointer=gps;
//send buffer
c_frombuffer=buffer[0];//c_frombuffer now contains 'U'
int_pointer=(int*)&buffer;
int_pointer+=1;
id_frombuffer=*int_pointer;//id_frombuffer now contains 1
gps_pointer=(gpscoords*)&buffer;
gpscoords+=5;
gps_frombuffer=*pointer;//gps_frombuffer now contains "some gps contend"
void sendupdate(unsigned char id,gpscoords gps)
{
char buffer[2+sizeof(gpscoords)];
gpscoords *gps_pointer;
buffer[0]='U';
buffer[1]=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=2;
*gpspointer=gps;
send(socket, buffer, 2+sizeof(gpscoords), flags);
}
void do_update(int sockfd, struct sockaddr_in *clientaddr)
{
char buffer[2+sizeof(gpscoords)];
recv(sockfd, buffer, 2+sizeof(gpscoords), flags);
unsigned char id_frombuffer=buffer[1];
gpscoords *gpspointer=(gpscoords*)&buffer;
gpspointer+=2;
update_client(id_frombuffer, gpspointer);
}