教你写socket(一个项目例子的socket部分)

我刚学过socket,自学的.看了一个例子.想和还不会的同志分享一下,如果你是高手那就算了.

注: 1表示自己写的.2表示提供的-不用自己写的.
void CListenDlg::OnButton1()
{
    // TODO: Add your control notification handler code here
    CWinThread *pThread=NULL;                       CButton* pBtn=(CButton *)GetDlgItem(IDC_BUTTON1);     //2
    int n=pBtn->GetCheck();     //2                  
    m_HostIp=GetIp();           //1 得到本机IP        
    if(1==n)     //开始监听
    {
        if(CreateSock()!=0)     //1 - 建立createsock成=0
        {    
              AfxMessageBox("WinSock设置失败");        
              DestroyWindow();     //2 销毁windows    
        }
        else
        {
              b_IsRun=TRUE;
              pThread=AfxBeginThread(RecvIpPro,this); //2 启动线程
        }
        pBtn->SetWindowText("停止监听");     //2
    }
    else //停止监听
    {
        b_IsRun=FALSE;
        if(pThread)               //pthread=null    
        {
              TerminateThread(pThread->m_hThread, 0);                                                             //2 该函数用来结束由hThread
                                                      //参数指定的线程,并把0设成该线程的退出码
                                          CloseHandle(pThread->m_hThread);     //2
        }
        if(m_RawSock)
              closesocket(m_RawSock);
        pBtn->SetWindowText("开始监听");
    }
}
//得到本机IP
char* GetIp()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    char name[255];
    char *ip;
    PHOSTENT hostinfo;
    wVersionRequested = MAKEWORD( 2, 0 );
    if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )//wsastartup成功返回0
    {
       
        if( gethostname ( name, sizeof(name)) == 0) //2 获得本机的名字
        {
              if((hostinfo = gethostbyname(name)) != NULL)//2 得到IP地址
              {
              ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
    //2 将参数in所指的网络二进制的数字转换成网络地址,然/后将指向此网络
    // 地址字符串的指针返回。 返回值. 成功则返回字符串指针,失败则返回NULL。
              }
        }
       
        WSACleanup( );
    }
    return ip;
}
//建立原始套接字
int CListenDlg::CreateSock()
{
    int err;
    char name[10];                  
    hostent *pHostent;
    int port=8310;                   //端口号,自定义5001,8080 ……
    SOCKADDR_IN sockaddr;
    m_RawSock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);     //2 互联网,流操作,0
    if(m_RawSock==INVALID_SOCKET)                       //若socket没有创建成
    {    
        return WSAGetLastError();                       //2 socket创建失败
    }
    err=gethostname(name,10);     //2 获得本机的名字
    if(err==SOCKET_ERROR)        
    {
        return WSAGetLastError();                       //2 取本机用户名失败
    }
    pHostent=gethostbyname (name);                     //获得你的机器的IP 地址

    sockaddr.sin_family=AF_INET;
    sockaddr.sin_port=htons(port);
    memcpy(&sockaddr.sin_addr.s_addr,pHostent->h_addr_list[0],
        pHostent->h_length);                             //ip 地址
   
    err=bind(m_RawSock,(SOCKADDR *)&sockaddr,sizeof(sockaddr));//绑定(将端口,ip和socket)
    if(err==SOCKET_ERROR)
    {
        return WSAGetLastError(); //取本机用户名,失败未绑定
    }
    BOOL bOptval=TRUE;

    //设置套节字选项
    setsockopt(m_RawSock,SOL_SOCKET,SO_REUSEADDR,(char*)&bOptval,sizeof(bOptval));//2 置套接口选项
    err=setsockopt(m_RawSock,IPPROTO_IP,IP_HDRINCL,(char*)&bOptval, //IP_HDRINCL该选项使之能操作IP头
        sizeof(bOptval));
    if(err==SOCKET_ERROR)
    {
        return WSAGetLastError(); //设置套节字选项失败
    }

    //把网卡置于混杂模式。获取IO操作的相关信息
    DWORD dwBufferLen[10] ;
    DWORD dwBufferInLen = 1 ;
    DWORD dwBytesReturned = 0 ;
    err=WSAIoctl (                             //2
        m_RawSock,           //一个指定的套接字                        
        SIO_RCVALL,     //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包 ,控制操作码                
        &dwBufferInLen,           //指向输入数据流的指针                      
        sizeof(dwBufferInLen),     //输入数据流的大小(字节数)                        
        &dwBufferLen,             //指向输出数据流的指针            
        sizeof(dwBufferLen),       //输出数据流的大小(字节数                  
        &dwBytesReturned,         //指向输出字节流数目的实数值          
        NULL,                 //指向一个WSAOVERLAPPED结构
        NULL                               //指向操作完成时执行的例程
        );//最后两参数设置非阻塞
    if(err==SOCKET_ERROR)
    {
        return WSAGetLastError();   //2 设置失败
    }
    return 0;
}
//在线程chi中不断接受IP包
UINT RecvIpPro(LPVOID lpParam)
{
    int err=0;
    int recvLen;
    CListenDlg* pDlg=(CListenDlg*)lpParam;
    char recvBuf[MAX_PACK_LEN]={0};//接受的最大的报文
    while(b_IsRun)
    {
        recvLen=recv(pDlg->m_RawSock,recvBuf,MAX_PACK_LEN,0);//接受数据
       
        if(err==SOCKET_ERROR)
        {
              if(WSAGetLastError()==WSAEWOULDBLOCK) //如果错误为阻塞那么将继续接受
                  continue;
              break;
        }
        //处理已经接受到的IP包
        EnterCriticalSection(&pDlg->m_ls);
        pDlg->SplitIpPack(recvBuf,recvLen); //分解IP包
        pDlg->ShowIpInfo(recvBuf,recvLen); //显示数据
        LeaveCriticalSection(&pDlg->m_ls);
    }
    return 0;
}
//分解IP包
void CListenDlg::SplitIpPack(char *pData, int len)
{
    IP_HEADER* pIpHead;
    pIpHead=(IP_HEADER*)pData; //转为IP头结构
    SOCKADDR_IN saSource,saDest; //中间变量分别为源IP地址结构和目标IP地址结构

    //得到包中协议
    int iProtocol;
    iProtocol=pIpHead->proto;
    //得到协议字符形式表示m_szProtocol
    strncpy(m_szProtocol,CheckProtocol(iProtocol),MAX_PROTO_TEXT_LEN);


    //得到源IP
    saSource.sin_addr.s_addr=pIpHead->sourceIP;
    strncpy(m_szSourceIP,inet_ntoa(saSource.sin_addr),MAX_ADDR_LEN);

    //得到目标IP
    saDest.sin_addr.s_addr=pIpHead->destIP;
    strncpy(m_szDestIP,inet_ntoa(saDest.sin_addr),MAX_ADDR_LEN);

    //得到TTL
    int ttl;
    ttl=pIpHead->ttl;
    wsprintf(m_szTTL,"%d",ttl);

    //得到头长度
    int ihLen=sizeof(unsigned long)*(pIpHead->h_lenver & 0xf);

    m_ihLen=ihLen;
    unsigned short srcPort=0,destPort=0;
    switch(iProtocol) {
    case IPPROTO_TCP:
        TCP_HEADER* pTcpHead;
        pTcpHead=(TCP_HEADER*)(pData+ihLen);
        srcPort=ntohs(pTcpHead->th_sport);
        destPort=ntohs(pTcpHead->th_dport);
        wsprintf(m_szSourcePort,"%d",srcPort);
        wsprintf(m_szDestPort,"%d",destPort);
        break;
                            }
}
//将协议int转为字符串
char* CListenDlg::CheckProtocol(int iProtocol)
{
    for(int i=0; i<MAX_PROTO_NUM; i++)
    {
        if(ProtoMap .ProtoNum==iProtocol)
        {
              return ProtoMap.ProtoText;
        }
    }
        return "";
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,以下是一个简单的Java socket示例: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9000); Socket clientSocket = serverSocket.accept(); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) { out.println(inputLine); } } } ### 回答2: 当然可以!这里给你一个简单的Socket的Java例子: 首先,你需要导入Java的网络编程包`java.net`和输入输出流包`java.io`。 然后,你可以通过以下步骤创建一个简单的Socket例子: 1. 创建服务器端:首先,你需要创建一个服务器Socket对象,并指定端口号,例如: ``` ServerSocket serverSocket = new ServerSocket(8888); ``` 2. 接受客户端连接请求:通过调用服务器Socket的`accept()`方法,等待并接受来自客户端的连接请求,并返回一个表示连接的Socket对象,例如: ``` Socket clientSocket = serverSocket.accept(); ``` 3. 创建输入输出流:为了从客户端读取数据和向客户端发送数据,你需要分别创建一个输入流和一个输出流对象,例如: ``` InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream(); ``` 4. 读取和发送数据:通过输入输出流,你可以读取和发送数据。例如,你可以使用`BufferedReader`来读取客户端发送的数据,然后使用`PrintWriter`向客户端发送数据,例如: ``` BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter writer = new PrintWriter(outputStream, true); String clientMessage = reader.readLine(); System.out.println("客户端发送的消息:" + clientMessage); writer.println("欢迎连接服务器!"); ``` 5. 关闭连接:当你完成数据的读取和发送后,你需要关闭连接和相应的输入输出流,例如: ``` reader.close(); writer.close(); clientSocket.close(); serverSocket.close(); ``` 6. 创建客户端:如果你想测试这个Socket例子,你可以创建一个客户端,并连接到服务器。首先,创建一个Socket对象,并指定服务器IP和端口号,例如: ``` Socket socket = new Socket("服务器IP地址", 8888); ``` 7. 创建输入输出流:然后,为了从服务器读取数据和向服务器发送数据,同样地,你需要分别创建一个输入流和一个输出流对象,例如: ``` InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); ``` 8. 读取和发送数据:同样地,使用输入输出流你可以读取和发送数据。例如,你可以使用`BufferedReader`来读取服务器发送的数据,然后使用`PrintWriter`向服务器发送数据,例如: ``` BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter writer = new PrintWriter(outputStream, true); writer.println("Hello, Server!"); String serverMessage = reader.readLine(); System.out.println("服务器发送的消息:" + serverMessage); ``` 9. 关闭连接:最后,在完成数据的读取和发送后,记得关闭连接和相应的输入输出流,例如: ``` reader.close(); writer.close(); socket.close(); ``` 这就是一个简单的Socket的Java例子。你可以根据自己的需求和场景进行修改和扩展。希望能帮到你! ### 回答3: 当然可以!以下是一个简单的Socket Java例子: ```java import java.io.*; import java.net.*; public class SocketExample { public static void main(String[] args) { // 客户端 try { // 创建一个Socket对象,指定服务器的IP地址和端口号 Socket socket = new Socket("localhost", 8888); // 获取输出流,用于向服务器发送数据 OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream); // 发送数据 printWriter.write("Hello, Server!"); printWriter.flush(); // 获取服务器响应 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String response = bufferedReader.readLine(); // 打印服务器响应 System.out.println("服务器响应:" + response); // 关闭流和Socket连接 printWriter.close(); bufferedReader.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ```java import java.io.*; import java.net.*; public class ServerSocketExample { public static void main(String[] args) { // 服务器端 try { // 创建一个ServerSocket对象,指定端口号 ServerSocket server = new ServerSocket(8888); System.out.println("等待客户端连接..."); // 等待客户端连接 Socket socket = server.accept(); System.out.println("客户端已连接!"); // 获取客户端的输入流,用于读取客户端发送的数据 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String request = bufferedReader.readLine(); // 打印客户端发送的数据 System.out.println("客户端请求:" + request); // 创建输出流,用于向客户端发送响应 OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream); // 发送响应 printWriter.write("Hello, Client!"); printWriter.flush(); // 关闭流和Socket连接 printWriter.close(); bufferedReader.close(); socket.close(); server.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 上述例子中,我们创建了一个简单的Socket连接。客户端通过Socket对象向服务器发送一条消息,服务器接收到后返回一条响应消息给客户端。请将上述代码分别保存到`SocketExample.java`和`ServerSocketExample.java`文件中,并编译运行。 注意:在运行服务器代码之前,请确保没有其他程序正在使用相同的端口号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值