Linux 父子进程使用TCP连接通信connect错误

li32768 2009-12-10 02:31:31
函数功能是父子进程使用TCP socket进行通信,只需要把字符串显示出来,运行提示错误是
at line 176 connect ERROR: con_rtn = -1, errno = 22 Invalid argument
不知何故?
/*
*function : TCP communication with a forked subtask
struct sockaddr_un
{
sa_family_t sun_family; // PF_NUIX or AF_UNIX or AF_LOCAL
char sun_path[UNIX_PATH_MAX]; //name of path;
};
//usr/include/linux/socket.h
typedef unsigned short sa_family_t;
struct sockaddr //this is general structure;
{
unsigned short sa_family; //AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
//usr/include/netinet/in.h
struct sockaddr_in //internet socket, can convert between above and it;
{
short int sin_family; //address cluster
unsigned short int sin_port; //port number
struct in_addr; //ip address
unsigned char sin_zero[8]; //for the same size as struct sockaddr
};
struct in_addr
{
unsigned long s_addr;
};
inet_addr()is used to convert general ip 192.168.0.1 int 32bits ip 0xc0a80001;

// return actual bytes been sent. flag always been 0, if error errno will be set;
int send(int sockfd, const void* msg, int len, int flags);

// use unlinked diagram to send message, so need sockaddr to define ip and port, in general, tolen is sizeof(struct sockaddr), and return value as above;
int sendto(int sockfd, const void* msg, int len, unsigned int flags, const struct sockaddr* to, int tolen);

//
int recv(int sockfd, void* buf, int len, unsigned int flags);

//
int recvfrom(int sockfd, void* buf, int len, unsigned int flags, struct sockaddr* from, int*fromlen);
once you use diagram socket, but use connect, you can use send() and recv() too, but this socket will still use diagram for service in transport layer, but in send or receive, kernel will add source and destination address for it;
close(sockfd) or int shutdown(int sockfd, int how) to end a data transport;


*create time : 2009/12/07 13:50
*modify time :
*history :
*/


#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/shm.h>

#include <errno.h>
extern int errno;
extern char* strerro(int );

char path[] = {"/tmp/socketmy"}; /* socket name, */

int main(void)
{
struct sockaddr_un sock;

int len=sizeof(sock);
int pid; /* child task's process id */
int soc; /* socket file descriptor */
int con_soc;
int lisn_rtn;
int bind_rtn;
int con_rtn;
int com_soc;
char buffer[80];

errno = 0;

memset((char *) &sock, 0, sizeof(sock));
strcpy(sock.sun_path, path);
sock.sun_family = AF_UNIX;
unlink(path);

/* establish and initialize TCP socket struct */
soc = socket(AF_UNIX, SOCK_STREAM, 0);

if (soc < 0)
{
printf("at line %d soc = socket error,soc = %d errno = %d %s\n", __LINE__,soc, errno, strerror(errno));
exit(-1);
}


/* create child subtask */
if((pid = fork()) == 0)
{
/* publish the socket name we listen to */

bind_rtn = bind(soc, (struct sockaddr *) &sock, sizeof(struct sockaddr_un));
if (bind_rtn < 0)
{
close(soc);
unlink(path);
printf("at line %d bind ERROR, bind_rtn = %d, errno= %d %s\n", __LINE__, bind_rtn, errno, strerror(errno));
exit(-1);
}

/* accept connection */
lisn_rtn = listen(soc, 1);
if(lisn_rtn < 0)
{
unlink(path);
close(soc);
printf("at line %d listen ERROR: lisn_rtn = %d, errno = %d %s\n", __LINE__, lisn_rtn, errno, strerror(errno));
exit (-1);
}
com_soc = accept(soc, (struct sockaddr *) &sock, &len);
if (com_soc < 0)
{
unlink(path);
close(soc);
printf("at line %d accept ERROR:com_soc = %d, errno = %d %s\n", __LINE__, com_soc, errno, strerror(errno));
}

/* echo messages received from parent back to user */
while(1)
{
recv(soc, buffer, sizeof(buffer), 0);
/* recvfrom(soc, buffer, sizeof(buffer), 0,
(struct sockaddr *) &sock, &len);*/
printf("child: %s", buffer);
if(strncmp(buffer, "EXIT", 4) == 0) /* exit request */
{
unlink(path);
printf("now you EXIT, bye\n");
/*puts("Bye!");*/
close(soc);
break;
}
}

/* Child exit */
exit(0);
}

/* connect to server socket created by our child subtask */
sleep(2); /*wait for setup */
/*con_soc = socket(AF_UNIX, SOCK_STREAM, 0);*/
con_rtn = connect(soc, (struct sockaddr *) &sock, sizeof(struct sockaddr));
if (con_rtn < 0)
{
/*unlink(path);
close(soc);*/
printf("at line %d connect ERROR: con_rtn = %d, errno = %d %s\n", __LINE__, con_rtn, errno, strerror(errno));
exit(-1);
}

/* send a message typed from interactive user to child subtask */
while(1)
{
sleep(1); /* response time */
printf("\nEnter a message: ");
/*fflush(stdout);*/
fgets(buffer, sizeof(buffer), stdin);

send(soc, buffer, strlen(buffer)+1, 0);
/*sendto(soc, buffer, strlen(buffer)+1, 0,
(struct sockaddr *) &sock, sizeof(sock));*/

if(strncmp(buffer, "EXIT", 4) == 0) /* exit request */
{
close(soc);
break;
}
}

/* await Child exit */
waitpid(pid);

return 0;
}
...全文
431 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
li32768 2009-12-10
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hairetz 的回复:]
http://203.208.39.132/search?q=cache:FTUwot93TS4J:hi.baidu.com/leivli/blog/item/8454cd008a88f5d1277fb530.html+socket+errno+%3D+22&cd=9&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy29hreDopD_7ZjY1i16gyxTRiTqvgg


其中22号错误为EINVAL(error msg: Invalid Argument)
man 2 accept 可知对应原因:
EINVAL Socket is not listening for connections.
即sockfd在accept之前没有listen调用,即没有在listen已经接收的连接请求队列中。
但现实中还有其它情况会造成这问题:
1. 在参数1 sockfd处出错,多半情况是sockfd值非法,也即是没有绑定(bind),监听(listen)或者是负值等等;2. 出错情况2:在参数3处出错,没有给addrlen传入合法的值,或者是没有初始化(addrlen= sizeof(addr)), 按道理来说,第3个参数是socklen_t的指针,只要声明一个socklen_t的变量len,然后传递地址进去即可,但实际中,我这样做,有时accept就会出现EINVAL的错误,后来查找资料发现,得在accept前将len赋值,即len = sizeof(struct sockaddr),然后再传递&len进去即可。
[/Quote]
我这个是在connect的时候出错的,前面我做了完整的参数检查,如果参数不对就退出了,所以参数没有不合法就该已经退出了,我也修改了那个长度使用了先用变量存长度然后作为参数,但错误依旧,这个不是编译出错,而是运行时候出错,原来的程序来自于 Linux Cluster 的一本经典的书但是示例没有错误检查,我加了,但就是不行,如果你遇到过类似的,你编译实验一下把正确的给我下我结贴
Wenxy1 2009-12-10
  • 打赏
  • 举报
回复
参数错误,检查参数嘛。
  • 打赏
  • 举报
回复
http://203.208.39.132/search?q=cache:FTUwot93TS4J:hi.baidu.com/leivli/blog/item/8454cd008a88f5d1277fb530.html+socket+errno+%3D+22&cd=9&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy29hreDopD_7ZjY1i16gyxTRiTqvgg


其中22号错误为EINVAL(error msg: Invalid Argument)
man 2 accept 可知对应原因:
EINVAL Socket is not listening for connections.
即sockfd在accept之前没有listen调用,即没有在listen已经接收的连接请求队列中。
但现实中还有其它情况会造成这问题:
1. 在参数1 sockfd处出错,多半情况是sockfd值非法,也即是没有绑定(bind),监听(listen)或者是负值等等;2. 出错情况2:在参数3处出错,没有给addrlen传入合法的值,或者是没有初始化(addrlen= sizeof(addr)), 按道理来说,第3个参数是socklen_t的指针,只要声明一个socklen_t的变量len,然后传递地址进去即可,但实际中,我这样做,有时accept就会出现EINVAL的错误,后来查找资料发现,得在accept前将len赋值,即len = sizeof(struct sockaddr),然后再传递&len进去即可。

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧