我最近移植了一个我写的linux应用程序,它广泛使用BSD套接字来进行winsock。代码似乎在linux上运行得很好,并且它在windows上编译得很好,但是当运行可执行文件时,我得到一个带有以下内容的消息框:
The application was unable to start correctly (0xc0000022). Click OK to close the application.
当然,我搜索了有关该错误的内容,并且主要指向了防病毒问题。我收集到应用程序无法以某种方式读取DLL,所以我尝试下载winsock.dll的副本并将其丢弃在我的可执行文件的运行路径中,但无济于事。我还在可执行文件上运行了依赖walker,它给出了很长的错误列表。大多数错误只是警告(例如找到多种CPU类型),但我注意到Error: A circular dependency was detected
引起了人们的注意。
正如我所说,代码在linux上按原样运行。这是我的tcp.c:
#include "tcp.h"
#define BUFSIZE 2048
#if defined(_WIN32)
#include <winsock2.h>
typedef int socklen_t;
struct pollfd {
SOCKET fd;
short events;
short revents;
};
#define poll(X,Y,Z) winpoll(X,Y,Z)
#define POLLOUT 1
#define POLLIN 0
static int winpoll(struct pollfd *pfd, int ignored, int ignored2) {
fd_set rfds;
struct timeval zero = {0};
int retval;
FD_ZERO(&rfds);
FD_SET(pfd->fd, &rfds);
if (pfd->events == POLLOUT) {
retval = select(1,NULL,&rfds,NULL,&zero);
} else {
retval = select(1,&rfds,NULL,NULL,&zero);
}
if (retval < 0) {
perror("select");
}
return retval;
}
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/poll.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <ifaddrs.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define BIND(SOCK,ADDR) bind(SOCK,(struct sockaddr*)&(ADDR),sizeof(struct sockaddr_in))
#define CONN(SOCK,ADDR) connect(SOCK,(struct sockaddr*)&(ADDR),sizeof(struct sockaddr_in))
void tcp_wrapup(void)
{
#if defined(_WIN32)
WSACleanup();
#endif
}
void tcp_setup(void)
{
#if defined(_WIN32)
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
#endif
}
static void set_nonblocking(int fd)
{
#if defined(_WIN32)
unsigned long mode = 1; /* non-blocking */
ioctlsocket(fd, FIONBIO, &mode);
#else
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK);
#endif
}
int tcp_server_init(unsigned short port)
{
int server_sock;
struct sockaddr_in server_addr = {0};
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) { perror("sock"); return -1; }
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (BIND(server_sock,server_addr) < 0) { perror("bind"); return -1; }
set_nonblocking(server_sock);
if (listen(server_sock, 0) < 0) { perror("listen"); return -1; }
return server_sock;
}
int tcp_server_poll(int server_sock)
{
int client_sock;
client_sock = accept(server_sock,NULL,NULL);
if (client_sock < 0) {
return -1;
}
return client_sock;
}
int tcp_client_init(unsigned int ip, unsigned short port)
{
int client_sock;
struct sockaddr_in client_addr = {0};
client_sock = socket(AF_INET, SOCK_STREAM, 0);
if (client_sock < 0) { perror("socket"); return -1; }
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htonl(ip);
client_addr.sin_port = htons(port);
set_nonblocking(client_sock);
/* Note: WILL fail, operation in progress, non-blocking sockets wait for
* handshake. */
CONN(client_sock,client_addr);
return client_sock;
}
void tcp_send(int sock, const char *msg)
{
int status;
struct pollfd myfd;
myfd.fd = sock;
myfd.events = POLLOUT;
status = poll(&myfd,1,0);
if (status == 1) {
if (send(sock, msg, strlen(msg)+1, 0) < 0) {
perror("send");
}
}
}
int tcp_recv(int sock, char *buf, int max)
{
int status;
struct pollfd myfd;
myfd.fd = sock;
myfd.events = POLLIN;
status = poll(&myfd,1,0);
if (status == 1) {
int ret;
if ((ret = recv(sock,buf,max,0)) < 0) {
return 0;
}
return ret;
}
return 0;
}
void tcp_close(int sock)
{
#if defined(_WIN32)
closesocket(sock);
#else
if (close(sock) < 0) {
perror("close");
}
#endif
}
unsigned int tcp_str_to_ip(const char *ip)
{
#if defined(_WIN32)
int bytes[4];
sscanf(ip,"%d.%d.%d.%d",&bytes[0],&bytes[1],&bytes[2],&bytes[3]);
return ntohl(((bytes[0]<<24) & 0xFF) |
((bytes[1]<<16) & 0xFF) |
((bytes[2]<<8) & 0xFF) |
(bytes[3] & 0xFF));
#else
struct addrinfo *cursor;
struct addrinfo *server = NULL;
getaddrinfo(ip,NULL,NULL,&server);
for (cursor = server; cursor; cursor = cursor->ai_next) {
if (cursor->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)cursor->ai_addr;
return ntohl(addr->sin_addr.s_addr);
}
}
return ntohl((unsigned int)inet_addr(ip));
#endif
}
char *tcp_ip_to_str(unsigned int ip)
{
struct in_addr addr;
addr.s_addr = htonl(ip);
return inet_ntoa(addr);
}
unsigned short tcp_get_port(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getpeername(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getpeername");
return -1;
}
return ntohs(addr.sin_port);
}
unsigned int tcp_get_ip(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getpeername(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getpeername");
return -1;
}
return ntohl(addr.sin_addr.s_addr);
}
unsigned short tcp_get_local_port(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getsockname(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getsockname");
return -1;
}
return ntohs(addr.sin_port);
}
unsigned int tcp_get_local_ip(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getsockname(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getsockname");
return -1;
}
return ntohl(addr.sin_addr.s_addr);
}
我的tcp.h标题:
#ifndef _TCP_H
#define _TCP_H
typedef int TCP_Socket;
/* <0 means no connection, try again */
TCP_Socket tcp_server_init(unsigned short);
TCP_Socket tcp_server_poll(TCP_Socket);
TCP_Socket tcp_client_init(unsigned int, unsigned short);
void tcp_send(TCP_Socket, const char *);
int tcp_recv(TCP_Socket, char *, int); /* 0 = no data */
void tcp_close(TCP_Socket);
unsigned int tcp_str_to_ip(const char *);
char *tcp_ip_to_str(unsigned int); /* in static buf */
unsigned short tcp_get_port(TCP_Socket);
unsigned int tcp_get_ip(TCP_Socket);
unsigned short tcp_get_local_port(TCP_Socket);
unsigned int tcp_get_local_ip(TCP_Socket);
/* Windows needs wrapup code. */
void tcp_wrapup(void);
void tcp_setup(void);
#endif /* _TCP_H */
对于命令行,windows版本只是将-lwsock32
添加到linux版本使用的命令的末尾。知道如何让我的代码工作吗?
我尝试使用调试模式进行编译,它仍然提供相同的错误代码。我使用break main运行gdb,在它甚至可以击中主断点之前它崩溃了During startup program exited with code 0xc0000022
。这让我相信它可能是代码之外的问题?或者可能是代码的权限?