zoukankan      html  css  js  c++  java
  • C语言写了一个socket server端,适合windows和linux,用GCC编译运行通过

    ///////////////////////////////////////////////////////////////////////////////
    /*
    gcc -Wall -o s1 s1.c -lws2_32
    */
    ///////////////////////////////////////////////////////////////////////////////

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>

    #define _WIN32_WINNT 0x501
    #define PORT 4000
    #define IP_ADDRESS "127.0.0.1"
    ///////////////////////////////////////////////////////////////////////////////
    // SK

    #ifdef _WIN32_WINNT
    #include <ws2tcpip.h>
    #include <winsock2.h>
    WSADATA Ws;
    #else
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/un.h>
    #include <netdb.h>
    #endif

    ///////////////////////////////////////////////////////////////////////////////
    // SK

    void connect_inet_socket( int *psockfd, const char* host, int port );

    #ifdef _WIN32_WINNT
    void connect_windows_socket( int *psockfd, const char* pathname );
    #else
    void connect_unix_socket( int *psockfd, const char* pathname );
    #endif

    void writebuffer_socket( int sockfd, const void *data, int len );
    void readbuffer_socket( int sockfd, void *data, int len );
    void shutdown_socket( int sockfd );

    ///////////////////////////////////////////////////////////////////////////////
    // SK
    /* Access to sockets needs to be done with a wrapper function 'connect_socket'
    and it is substituted by 'connect_windows_socket' or by 'connect_unix_socket'
    ( depends on a state of the macro _WIN32 ) during preprocessing phase of
    the compilation.
    For portability 'connect_windows_socket' and 'connect_unix_socket' shouldn't
    be used directly and the wrapper function 'connect_socket' must be used instead.
    */

    #ifdef _WIN32_WINNT
    #define connect_socket connect_windows_socket
    #else
    #define connect_socket connect_unix_socket
    #endif

    int socket_desc;
    struct sockaddr_in server;

    ///////////////////////////////////////////////////////////////////////////////
    /* Opens an internet socket.

    Note that fortran passes an extra argument for the string length,
    but this is ignored here for C compatibility.

    Args:
    psockfd: The id of the socket that will be created.
    port: The port number for the socket to be created. Low numbers are
    often reserved for important channels, so use of numbers of 4
    or more digits is recommended.
    host: The name of the host server.
    */

    void connect_inet_socket( int *psockfd, const char* host, int port )
    {
    int sockfd, ai_err;

    // creates an internet socket

    // fetches information on the host
    struct addrinfo hints, *res;
    char service[256];

    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    hints.ai_flags = AI_PASSIVE;

    //sprintf(service, "%d", port); // convert the port number to a string
    //ai_err = getaddrinfo(host, service, &hints, &res);
    //if (ai_err!=0) {
    // printf("Error code: %i ",ai_err);
    // perror("Error fetching host data. Wrong host name?");
    // exit(-1);
    //}

    // creates socket
    //sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    sockfd = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (sockfd < 0) {
    perror("Error opening socket");
    exit(-1);
    }
    else
    {
    printf("creates socket:%d ", sockfd);
    }

    // makes connection
    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
    perror("Error opening INET socket: wrong port or server unreachable");
    exit(-1);
    }
    freeaddrinfo(res);

    *psockfd = sockfd;
    }

    ///////////////////////////////////////////////////////////////////////////////
    // SK
    /* Opens a socket.

    Note that fortran passes an extra argument for the string length,
    but this is ignored here for C compatibility.

    Args:
    psockfd: The id of the socket that will be created.
    pathname: The name of the file to use for sun_path.
    */

    #ifdef _WIN32_WINNT

    void connect_windows_socket( int *psockfd, const char* pathname )
    {
    // Required functionality for Windows

    // ...
    }

    #else

    void connect_unix_socket( int *psockfd, const char* pathname )
    {
    // Required functionality for Unix

    int sockfd, ai_err;

    struct sockaddr_in serv_addr;

    printf("Connecting to :%s: ",pathname);

    // fills up details of the socket addres
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sun_family = AF_UNIX;
    /* Beware of buffer over runs
    UNIX Network Programming by Richard Stevens mentions
    that the use of sizeof() is ok, but see
    http://mail-index.netbsd.org/tech-net/2006/10/11/0008.html
    */
    if ((int)strlen(pathname)> sizeof(serv_addr.sun_path)) {
    perror("Error opening UNIX socket: pathname too long ");
    exit(-1);
    } else {
    strcpy(serv_addr.sun_path, pathname);
    }
    // creates a unix socket

    // creates the socket
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

    // connects
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
    perror("Error opening UNIX socket: path unavailable, or already existing");
    exit(-1);
    }
    *psockfd = sockfd;
    }

    #endif

    ///////////////////////////////////////////////////////////////////////////////
    /* Writes to a socket.

    Args:
    sockfd: The id of the socket that will be written to.
    data: The data to be written to the socket.
    len: The length of the data in bytes.
    */

    void writebuffer_socket( int sockfd, const void *data, int len )
    {
    int n;

    n = write(sockfd, (char *) data, len);
    if (n < 0) {
    perror("Error writing to socket: server has quit or connection broke");
    exit(-1);
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    /* Reads from a socket.

    Args:
    sockfd: The id of the socket that will be read from.
    data: The storage array for data read from the socket.
    len: The length of the data in bytes.
    */

    void readbuffer_socket( int sockfd, void *data, int len )
    {
    int n, nr;
    char *pdata;

    pdata = (char *) data;
    n = nr = read(sockfd, pdata, len);

    while (nr > 0 && n < len) {
    nr = read(sockfd, &(pdata[n]), len - n);
    n += nr;
    }
    if (n == 0) {
    perror("Error reading from socket: server has quit or connection broke");
    exit(-1);
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    /* Shuts down the socket.
    */

    void shutdown_socket( int sockfd )
    {
    shutdown( sockfd, 2 );
    close( sockfd );
    }

    DWORD WINAPI ClientThread(LPVOID lpParameter)
    {
    SOCKET CientSocket = (SOCKET)lpParameter;
    int Ret = 0;
    char RecvBuffer[1024];
    char message[] = "Hello Master HaKu!";

    while ( 1 )
    {
    memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
    Ret = recv(CientSocket, RecvBuffer, 1024, 0);
    if ( Ret == 0 || Ret == SOCKET_ERROR )
    {
    printf("客户端退出! ");
    break;
    }
    printf("接收到客户信息为%s ", RecvBuffer);
    //Ret = send(CientSocket, "hello world", (int)strlen("hello world"), 0);
    //Ret = write(CientSocket, "hello world", sizeof("hello world"));
    //write(CientSocket, message, sizeof(message));
    send(CientSocket, "hello world", strlen("hello world"), 0);
    //if ( Ret == 0 || Ret == SOCKET_ERROR )
    //{
    printf("返回给客户端%s ", message);
    // break;
    //}
    }

    return 0;
    }


    int main(void)
    {
    int *socket_desc;
    SOCKET ServerSocket, ClientSocket;
    struct sockaddr_in LocalAddr, ClientAddr;
    int Ret = 0;
    int AddrLen = 0;
    HANDLE hThread = NULL;
    char SendBuffer[MAX_PATH];
    char message[30] = "Hello Master HaKu!";

    #ifdef _WIN32_WINNT
    //Init Windows Socket
    if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
    {
    printf("Init Windows Socket Failed");
    return -1;
    }
    #endif

    //connect_inet_socket(socket_desc, "http://blog.csdn.net", 80);
    //Create socket
    ServerSocket = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (socket_desc == -1)
    {
    printf("Could not create socket");
    }

    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
    LocalAddr.sin_port = htons(PORT);
    memset(LocalAddr.sin_zero, 0x00, 8);

    //Bind Socket
    Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
    if ( Ret != 0 )
    {
    printf("Bind Socket Failed");
    //return -1;
    }
    //listen

    Ret = listen(ServerSocket, 10);
    if ( Ret != 0 )
    {
    printf("listen Socket Failed");
    //return -1;
    }

    printf("服务端已经启动 ");

    while ( 1 )
    {
    AddrLen = sizeof(ClientAddr);
    ClientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
    if ( ClientSocket == INVALID_SOCKET )
    {
    printf("Accept Failed");
    break;
    }

    //write(ClientSocket, message, sizeof(message));
    send(ClientSocket, message, strlen(message), 0);

    printf("客户端连接 ");

    hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);
    if ( hThread == NULL )
    {
    printf("Create Thread Failed!");
    break;
    }

    CloseHandle(hThread);
    }

    closesocket(ServerSocket);
    closesocket(ClientSocket);
    WSACleanup();

    return 0;
    }

  • 相关阅读:
    第1章 初涉MySQL
    成绩转换
    【JSTL】--附加:c:import,c:url;c:param,c:redirect--drp217
    【JSTL】--JSTL表达式:c:forEach,varstatus/begin end/循环控制标签--drp215
    【JSTL】--JSTL表达式:c:forEach--drp215
    【JSTL】--JSTL表达式:c:set,c:if,c:choose,--drp214
    【JSTL】--c:out演示--drp213
    【JSTL】--测试EL表达式--drp212~
    【JSTL】--读取实体成员变量吗?--drp212
    【JSTL】--测试EL表达式--drp212
  • 原文地址:https://www.cnblogs.com/bdccloudy/p/7678063.html
Copyright © 2011-2022 走看看